Por que '397' é usado para a substituição do ReSharper GetHashCode?

150

Como muitos de vocês, eu uso o ReSharper para acelerar o processo de desenvolvimento. Quando você o usa para substituir os membros de igualdade de uma classe, o código-gen que produz para GetHashCode () se parece com:

    public override int GetHashCode()
    {
        unchecked
        {
            int result = (Key != null ? Key.GetHashCode() : 0);
            result = (result * 397) ^ (EditableProperty != null ? EditableProperty.GetHashCode() : 0);
            result = (result * 397) ^ ObjectId;
            return result;
        }
    }

É claro que tenho alguns dos meus membros lá, mas o que estou querendo saber é por que 397?

  • EDIT: Então, minha pergunta seria melhor redigida como, existe algo 'especial' sobre o número primo 397 fora dele ser um número primo?
programador
fonte

Respostas:

166

Provavelmente porque 397 é um primo de tamanho suficiente para fazer com que a variável de resultado transborde e misture um pouco os bits do hash, fornecendo uma melhor distribuição dos códigos de hash. Não há nada particularmente especial no 397 que o distinga de outros primos da mesma magnitude.

Nick Johnson
fonte
73
E 397 é feliz. Todos nós não queremos apenas ser felizes?
Russell B
2
Ok, mas por que tem que ser primo e por que tem exatamente essa magnitude? Se tiver que ser primo, por que não 2 ou 2147483647? Eu acho que para obter uma boa mutação (e a única razão para essa multiplicação é a mutação), não precisamos de número para ser primo. Precisamos que o multiplicador tenha relativamente o mesmo número ou zeros e uns, preferencialmente sem padrões explícitos. 397 = 110001101b está em conformidade. Ainda não tenho certeza sobre a magnitude.
Andriy K
5
Como Nick disse, não há nada de especial nisso. Ele NÃO PRECISA ser desse tamanho, é apenas um número grande o suficiente para que, ao calcular um hash, o resultado seja excedido (já que GetHashCode () retorna um Int32). Selecionar um primo é apenas útil para a distribuição; eu não tenho um diploma de matemática, então não vou tentar explicá-lo, mas a multiplicação por um primo terá um resultado mais bem distribuído do que a multiplicação por qualquer outro número arbitrário.
Ben Randall
16

O hash que o compartilhador usa parece uma variante do hash FNV . O FNV é frequentemente implementado com diferentes números primos. Há uma discussão sobre a escolha apropriada de números primos para FNV aqui .

kybernetikos
fonte