Warum wird '397' für die Überschreibung von ReSharper GetHashCode verwendet?

150

Wie viele von Ihnen verwende ich ReSharper, um den Entwicklungsprozess zu beschleunigen. Wenn Sie damit die Gleichheitsmitglieder einer Klasse überschreiben, sieht das für GetHashCode () erzeugte Code-Gen folgendermaßen aus:

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

Natürlich habe ich einige meiner eigenen Mitglieder dort, aber ich möchte wissen, warum 397?

  • EDIT: Meine Frage wäre also besser formuliert als: Gibt es etwas Besonderes an der 397-Primzahl, die keine Primzahl ist?
Programmierer
quelle

Antworten:

165

Wahrscheinlich, weil 397 eine Primzahl von ausreichender Größe ist, um zu bewirken, dass die Ergebnisvariable überläuft und die Bits des Hash etwas mischt, was eine bessere Verteilung der Hash-Codes ermöglicht. 397 hat nichts Besonderes an sich, das es von anderen Primzahlen gleicher Größe unterscheidet.

Nick Johnson
quelle
73
Und 397 ist glücklich. Wollen wir nicht alle nur glücklich sein?
Russell B
2
Okay, aber warum muss es prim sein und warum muss es genau so groß sein? Wenn es Primzahl sein muss, warum nicht 2 oder 2147483647? Ich denke, um eine schöne Mutation zu erhalten (und der einzige Grund für diese Multiplikation ist die Mutation), brauchen wir keine Zahl, um eine Primzahl zu sein. Wir brauchen einen Multiplikator, um eine relativ gleiche Anzahl oder Nullen und Einsen zu haben, vorzugsweise ohne explizite Muster. 397 = 110001101b entspricht. Immer noch nicht sicher über die Größe.
Andriy K
5
Wie Nick sagte, ist daran nichts Besonderes. Es muss nicht so groß sein, das ist nur eine Zahl, die groß genug ist, damit bei der Berechnung eines Hash das Ergebnis überläuft (da GetHashCode () ein Int32 zurückgibt). Die Auswahl einer Primzahl ist nur für die Verteilung hilfreich. Ich habe keinen Mathematikabschluss, daher werde ich nicht versuchen, sie zu erklären, aber die Multiplikation mit einer Primzahl führt zu einem Ergebnis, das besser verteilt ist als die Multiplikation mit einer anderen beliebigen Zahl.
Ben Randall
16

Der von Resharper verwendete Hash sieht aus wie eine Variante des FNV- Hash. FNV wird häufig mit unterschiedlichen Primzahlen implementiert. Es gibt eine Diskussion über die geeignete Wahl von Primzahlen für FNV hier .

kybernetikos
quelle