Pourquoi '397' est-il utilisé pour le remplacement de ReSharper GetHashCode?

150

Comme beaucoup d'entre vous, j'utilise ReSharper pour accélérer le processus de développement. Lorsque vous l'utilisez pour remplacer les membres d'égalité d'une classe, le code-gen qu'il produit pour GetHashCode () ressemble à:

    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;
        }
    }

Bien sûr, j'ai certains de mes propres membres là-dedans, mais ce que je veux savoir, c'est pourquoi 397?

  • EDIT: Donc, ma question serait mieux formulée comme suit: y a-t-il quelque chose de «spécial» à propos du nombre premier 397 en dehors du fait qu'il est un nombre premier?
programmeur
la source

Réponses:

166

Probablement parce que 397 est un nombre premier de taille suffisante pour faire déborder la variable de résultat et mélanger quelque peu les bits du hachage, fournissant une meilleure distribution des codes de hachage. Il n'y a rien de particulièrement spécial à propos de 397 qui le distingue des autres nombres premiers de la même grandeur.

Nick Johnson
la source
73
Et 397 est heureux. Ne voulons-nous pas tous être heureux?
Russell B
2
D'accord, mais pourquoi doit-il être primordial et pourquoi doit-il être de cette ampleur exacte? S'il doit être premier, pourquoi pas 2 ou 2147483647? Je suppose que pour obtenir une belle mutation (et la seule raison de cette multiplication est la mutation), nous n'avons pas besoin du nombre pour être premier. Nous avons besoin d'un multiplicateur pour avoir relativement le même nombre ou des zéros et des uns, de préférence sans motifs explicites. 397 = 110001101b est conforme. Toujours pas sûr de l'ampleur.
Andriy K
5
Comme Nick l'a dit, il n'y a rien de particulièrement spécial à ce sujet. Il n'a pas BESOIN d'avoir cette taille, c'est juste un nombre suffisamment grand pour que lorsque vous calculez un hachage, le résultat déborde (puisque GetHashCode () renvoie un Int32). La sélection d'un nombre premier est juste utile pour la distribution, je n'ai pas de diplôme en mathématiques donc je ne vais pas essayer de l'expliquer, mais la multiplication par un nombre premier aura un résultat plus bien distribué que la multiplication par tout autre nombre arbitraire.
Ben Randall
16

Le hachage utilisé par le resharper ressemble à une variante du hachage FNV . FNV est fréquemment implémenté avec différents nombres premiers. Il y a une discussion sur le choix approprié des nombres premiers pour FNV ici .

kybernetikos
la source