xorist eine gefährliche Standardfunktion, die beim Hashing verwendet wird. Es ist besser als andund or, aber das sagt nicht viel.
xorist symmetrisch, so dass die Reihenfolge der Elemente verloren geht. Also "bad"wird Hash das gleiche kombinieren wie "dab".
xor Ordnet paarweise identische Werte Null zu, und Sie sollten vermeiden, "allgemeine" Werte Null zuzuordnen:
Also (a,a)auf 0 abgebildet wird, und (b,b)auch auf 0 abgebildet wird als solche Paare sind fast immer häufiger als Zufälligkeit könnte bedeuten, Sie am Ende mit viel zu vielen Kollisionen auf Null , als Sie sollten.
Mit diesen beiden Problemen wird xores zu einem Hash-Kombinierer, der auf der Oberfläche halbwegs anständig aussieht, aber nicht nach weiterer Prüfung.
Bei moderner Hardware ist das Hinzufügen normalerweise ungefähr so schnell wie xor(es verbraucht wahrscheinlich mehr Strom, um dies zu erreichen, zugegebenermaßen). Die Wahrheitstabelle des Hinzufügens ähnelt der xordes betreffenden Bits, sendet jedoch auch ein Bit zum nächsten Bit, wenn beide Werte 1 sind. Dies bedeutet, dass weniger Informationen gelöscht werden.
Ist also hash(a) + hash(b)besser als hash(a) xor hash(b)wenn a==b, wenn das Ergebnis hash(a)<<1statt 0 ist.
Dies bleibt symmetrisch; so das "bad"und "dab"das gleiche Ergebnis erhalten bleibt ein Problem. Wir können diese Symmetrie für bescheidene Kosten brechen:
hash(a)<<1 + hash(a) + hash(b)
aka hash(a)*3 + hash(b). (Einmaliges Berechnen hash(a)und Speichern wird empfohlen, wenn Sie die Schichtlösung verwenden). Jede ungerade Konstante anstelle von 3wird eine kvorzeichenlose Ganzzahl mit " -bit" bijektiv auf sich selbst abbilden, da die Zuordnung auf vorzeichenlosen Ganzzahlen 2^kfür einige mathematisch modulo kist und jede ungerade Konstante relativ prim ist 2^k.
Für eine noch schickere Version können wir untersuchen boost::hash_combine, was effektiv ist:
size_t hash_combine( size_t lhs, size_t rhs ) {
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
return lhs;
}
Hier addieren wir einige verschobene Versionen von seedmit einer Konstanten (die im Grunde genommen zufällige 0s und 1s sind - insbesondere ist es die Umkehrung des Goldenen Schnitts als 32-Bit-Festkommafraktion) mit einer Addition und einem xor. Dies unterbricht die Symmetrie und führt zu einem gewissen "Rauschen", wenn die eingehenden Hash-Werte schlecht sind (dh stellen Sie sich vor, dass jede Komponente auf 0 gehasht wird - das oben Gesagte behandelt dies gut 1und erzeugt 0nach jedem Mähdrescher einen Abstrich von und s. Meine Naivität 3*hash(a)+hash(b)gibt einfach ein 0In aus dieser Fall).
(Für diejenigen, die mit C / C ++ nicht vertraut sind, size_tist a ein vorzeichenloser Ganzzahlwert, der groß genug ist, um die Größe eines Objekts im Speicher zu beschreiben. Auf einem 64-Bit-System ist es normalerweise eine 64-Bit-Ganzzahl ohne Vorzeichen. Auf einem 32-Bit-System , eine 32-Bit-Ganzzahl ohne Vorzeichen.)