Warum ist die XOR-Operation der Standard-Weg, um zu kombinieren hashes?
Sagen, Sie haben zwei hashes H(A)
und H(B)
und Sie wollen, Sie zu kombinieren. Ich habe gelesen, dass ein guter Weg, um zu kombinieren zwei hashes zu XOR
Ihnen, z.B. XOR( H(A), H(B) )
.
Die beste Erklärung, die ich gefunden habe berührt, wird hier kurz auf diese hash-Funktion-Richtlinien:
XORing zwei zahlen mit etwa zufällige Verteilung ergibt sich eine andere Zahl noch mit etwa zufällige Verteilung*, aber das kommt jetzt auf die beiden Werte.
...
* An jedem bit der beiden zahlen zu kombinieren, wird eine 0 ausgegeben wird, wenn die beiden bits gleich sind, sonst eine 1. In anderen Worten, in 50% der Kombinationen, eine 1 ausgegeben wird. Also, wenn die zwei Eingangs-bits jeweils eine ungefähr 50-50 chance, 0 oder 1, dann werden auch die Ausgangs-bit.
Können Sie erklären, der intuition und/oder der Mathematik dahinter, warum XOR sollten die Standard-Betrieb für die Kombination von hash-Funktionen (anstatt ODER-oder UND usw.)?
beachten Sie, dass die XOR sein kann oder nicht, ein "guter" Weg zu "kombinieren" - hashes, je nachdem, was Sie wollen, in einer "Kombination". XOR-Verknüpfung ist kommutativ: XOR(H(A),H(B)) entspricht der XOR - (H(B),H(A)). Dies bedeutet, dass die XOR ist nicht eine richtige Weg, um erstellen Sie eine Art von hash, der eine geordnete Sequenz von Werten, denn es erfasst nicht die Reihenfolge.
Neben dem Problem mit der Bestellung (Kommentar oben), gibt es problem mit gleichen Werten. XOR(H(1), H(1))=0 (für eine beliebige Funktion H), XOR(H(2) H(2))=0 und so weiter. Für beliebiges N: XOR(H(N) H(N))=0. Werte gleich oft passiert in realen Anwendungen, und es bedeutet, dass das Ergebnis der XOR-0 zu oft als gutes Haschisch.
Was benutzt du für geordnete Folge von Werten ? Sagen wir mal ich möchte einen hash des Zeitstempels oder eines index. (MSB weniger wichtig als LSB). Sorry, falls dieser thread ist 1 Jahr alt.
Verwandte: Was ist der beste Algorithmus für eine überschriebene System.Objekt.GetHashCode?
InformationsquelleAutor Nate Murray | 2011-05-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Unter der Annahme einheitlich zufällig (1-bit) - Eingänge der UND-Funktion-Ausgangs Wahrscheinlichkeitsverteilung ist 75%
0
und 25%1
. Umgekehrt, ODER ist 25%0
und 75%1
.Die XOR-Funktion ist 50%
0
und 50%1
daher ist es gut für die Kombination uniform Wahrscheinlichkeitsverteilungen.Dies kann man durch schreiben der Wahrheit Tabellen:
Übung: Wie viele logische Funktionen von zwei 1-bit Eingänge
a
undb
haben dieses einheitliche output-Verteilung? Warum ist die XOR am besten geeignet für den Zweck, die in Ihrer Frage?(0, a & b, a > b, a, a < b, b, a % b, a | b, !a & !b, a == b, !b, a >= b, !a, a <= b, !a | !b, 1)
die folgenden 50%-50% Verteilung von 0s und 1s, vorausgesetzt, a und b haben 50%-50% Verteilung von 0s und 1s:a, b, !a, !b, a % b, a == b
ich. e., das Gegenteil von XOR (EQUIV) benutzt worden sein könnte, sowie...Greg, das ist eine schreckliche Antwort. Die Glühbirne ging auf für mich, nachdem ich sah, Ihre ursprüngliche Antwort und schrieb meine eigene Wahrheit Tabellen. Ich als @Massa Antwort darüber, wie es werden 6 geeignete Operationen für die Aufrechterhaltung der Verteilung. Und während
a, b, !a, !b
wird die gleiche Verteilung wie Ihre jeweiligen Eingänge, verlieren Sie die Entropie von den anderen Eingang. Das heißt, XOR ist am besten geeignet für den Zweck der Kombination von hashes, weil wir wollen, zu erfassen Entropie von a und b.Ich habe noch nie gesehen % für XOR, oder nicht gleich.
Nein, das Ergebnis ist nicht eindeutig. Es gibt viele verschiedene Möglichkeiten zu generieren, die eine gegebene Folge R aus R = A XOR B. betrachten Sie beispielsweise 0010 XOR 1100, 1111 0001 XOR. Beide geben das Ergebnis 1110.
Yakk Punkte out, XOR können gefährlich sein, wie es produziert keine für identische Werte. Dies bedeutet
(a,a)
und(b,b)
beide produzieren gleich null, was in vielen (den meisten?) Fällen erhöht die Wahrscheinlichkeit von Kollisionen in hash-basierten Datenstrukturen.InformationsquelleAutor Greg Hewgill
xor ist eine gefährliche Standard-Funktion verwenden, wenn das hashing. Es ist besser als und und oder, aber das macht nicht viel sagen.
xor ist symmetrisch, so ist die Reihenfolge der Elemente geht verloren. So
"bad"
wird hash kombinieren die gleichen wie"dab"
.xor-Karten identische Werte auf null, und Sie sollten es vermeiden mapping "gemeinsame" Werte auf null:
So
(a,a)
bekommt die 0 zugeordnet, und(b,b)
bekommt auch 0 zugeordnet. Als solche Paare sind häufiger als Zufälligkeit könnte bedeuten, dass Sie am Ende mit viel zu viele Kollisionen bei null, als Sie sollten.Mit diesen beiden Problemen, xor am Ende ein hash-combiner, sieht halbwegs anständige auf der Oberfläche, nicht aber nach einer weiteren Inspektion.
Auf moderner hardware hinzufügen in der Regel etwa so schnell wie xor (es verwendet wahrscheinlich mehr Strom zu ziehen diese aus, zugegeben). Hinzufügen Wahrheit Tabelle ist ähnlich wie xor auf das bit in Frage, aber es sendet auch ein bit zum nächsten bit beendet, wenn beide Werte 1 sind. Dies bringt weniger Informationen.
So
hash(a) + hash(b)
ist besser, wenna==b
, das Ergebnis ist stattdessenhash(a)<<1
statt 0.Bleibt symmetrisch. Wir brechen diese Symmetrie für eine bescheidene Kosten:
aka
hash(a)*3 + hash(b)
. (Berechnunghash(a)
einmal und speichern ist zu empfehlen, wenn Sie verwenden Sie die Umschalt-Lösung). Jede ungerade Konstante anstelle von3
wird bijectively Karte einsize_t
(oder k-bit-unsigned-Konstante) zu sich selbst, als Karte auf unsigned-Konstanten math modulo2^k
für einigek
, und jede ungerade Konstante teilerfremd zu2^k
.Für einen noch eleganteren version, können wir untersuchen
boost::hash_combine
effektiv:hier fügen wir zusammen einige verschobene Versionen von
seed
mit einer Konstanten (das ist im Grunde zufällig0
s und1
s -- insbesondere ist die inverse der goldene Schnitt als ein 32-bit-fixed-point-Fraktion) mit etwas Zusatz und einem xor. Dies bricht die Symmetrie, und stellt einige "Lärm", wenn die eingehenden Hash-Werte schlecht sind (dh, stellen Sie sich vor jede Komponente hashes 0 -- die oben behandelt Sie gut, Sie generieren ein Abstrich von1
und0
s nach jedem kombinieren. Mir einfach die Ausgänge a0
).Für diejenigen, die nicht vertraut mit C/C++, eine
size_t
ist ein unsigned-integer-Wert, der groß genug ist, um zu beschreiben, die Größe eines Objekts im Speicher. Auf einem 64 bit-system, es ist in der Regel eine 64-bit-Ganzzahl. Auf einem 32 bit system ein 32-bit unsigned integer.hinzufügen von mehr bits zu
0x9e3779b9
.OK, vollständig zu sein... hier ist die volle Genauigkeit 64-bit-Konstante (berechnet mit long Double, unsigned long Long): 0x9e3779b97f4a7c16. Interessanterweise ist es auch noch. Re-doing die gleiche Berechnung mit PI statt der Goldenen Ratio ergibt: 0x517cc1b727220a95, die ungerade ist, anstelle von selbst, daher wohl "mehr prime" als die anderen Konstanten. Verwendet habe ich: std::cout << std::hex << (unsigned long long) ((1,0 L/3.14159265358979323846264338327950288419716939937510 L)*(powl(2.0 L,64.0 L))) << std::endl; mit cout.Präzision( numeric_limits<long double>::max_digits10 ); nochmals vielen Dank Yakk.
die inverse goldene-Schnitt-Regel für diese Fälle ist der erste seltsam Zahl gleich oder größer als die Berechnung, die Sie tun. So fügen Sie einfach 1. Es ist eine wichtige Zahl, weil die Sequenz von N * das Verhältnis, mod die maximale Größe (2^64 hier) legt der nächste Wert in der Sequenz genau an das Verhältnis in der Mitte die größte 'Lücke' in zahlen. Das web für die Suche "Fibonacci-hashing" für mehr info.
die richtige Zahl wäre 0.9E3779B97F4A7C15F39... Siehe link. Sie konnte sein Leid von der rund-um-auch-Regel (das ist gut für die Wirtschaftsprüfer), oder einfach, wenn Sie beginnen mit einem wörtlichen sqrt(5) Konstante, wenn Sie subtrahieren Sie 1 entfernen Sie die high-order bit, ein bit haben muss, verloren gegangen.
InformationsquelleAutor Yakk - Adam Nevraumont
Trotz seiner handlichen bit-mixing-Eigenschaften, XOR ist nicht ein guter Weg, um zu kombinieren hashes aufgrund seiner commutativity. Betrachten Sie, was passieren würde, wenn Sie gespeichert werden, ist die Permutationen von {1, 2, ..., 10} in einer hash-Tabelle der 10-Tupel.
Eine viel bessere Wahl ist
m * H(A) + H(B)
, wo m ist eine große ungerade Zahl ist.Kredit: Die oben genannten combiner war ein Tipp von Bob Jenkins.
long
und dann munge den oberen Teil zurück in den unteren Teil.m = 3
ist eigentlich eine gute Wahl und sehr schnell auf viele Systeme. Beachten Sie, dass für jede ungeradem
integer-Multiplikation ist modulo2^32
oder2^64
und ist daher invertierbar, so dass Sie nicht verlieren alle bits.Was passiert, wenn Sie hinausgehen, MaxInt?
statt jede ungerade Zahl ein wählen prime
das ist auch nicht notwendig, wenn die Kombination von hashes.
InformationsquelleAutor Marcelo Cantos
Xor kann der "Standard" Weg, um zu kombinieren, hashes, aber Greg Hewgill die Antwort zeigt auch, warum es hat seine Tücken:
Das xor von zwei identischen hash-Werte gleich null ist.
Im wirklichen Leben gibt es identische hashes sind häufiger, als man erwartet haben könnte. Dann könnten Sie feststellen, dass in diesen (nicht so seltene) Ausnahmefälle, die resultierenden kombinierten hashes sind immer die gleichen (null). Hash-Kollisionen wäre viel, viel häufiger, als Sie erwarten.
In ein erfundenes Beispiel könnte man das kombinieren der Hash-Passwörter von Benutzern aus verschiedenen websites, die Sie verwalten. Leider, eine große Anzahl von Benutzern wiederverwenden Ihre Kennwörter, und einen überraschenden Anteil des resultierenden hashes sind gleich null!
InformationsquelleAutor Leo Goodstadt
Gibt es etwas, was ich möchte ausdrücklich darauf hinweisen, für die anderen, die diese Seite finden. UND und ODER Schränken Sie die Ausgabe wie BlueRaja - Danny Pflughoe versucht zu zeigen, sondern besser definiert:
Zuerst möchte ich definieren zwei einfache Funktionen, die ich verwenden werde, dies zu erklären: Min() und Max().
Min(A, B) geben den Wert zurück, der kleiner, zwischen A und B, zum Beispiel: Min(1, 5) gibt 1 zurück.
Max(A, B) geben den Wert zurück, der größer zwischen A und B, zum Beispiel: Max(1, 5) liefert 5.
Wenn Sie gegeben sind:
C = A AND B
Dann können Sie feststellen, dass
C <= Min(A, B)
Wir wissen dies, weil es nichts ist, was man kann UND mit 0-bits von A oder B zu machen 1s. Also jedes null-bit bleibt ein null-bit und jedes bit hat eine chance, zu einem null-bit (und somit einen kleineren Wert).Mit:
C = A OR B
Das Gegenteil ist wahr:
C >= Max(A, B)
Mit diesem, sehen wir die logische Folge der UND-Funktion. Jedes bit, das ist schon eine nicht ORed in eine null, so bleibt es eine, aber jedes null-bit hat eine chance eine eins, und damit eine größere Anzahl.Dies impliziert, dass der Zustand der Eingang gilt Beschränkungen für die Ausgabe. Wenn Sie UND alles, was mit 90, Sie wissen, die Ausgabe ist gleich oder weniger als 90 unabhängig davon, was die andere Wert ist.
Für XOR gibt es keine STILLSCHWEIGENDE Beschränkung auf der Grundlage der Eingänge. Es gibt spezielle Fälle, wo Sie finden können, dass, wenn Sie eine XOR-byte mit 255 als die inverse aber jedes mögliche byte ausgegeben werden können. Jedes bit hat eine chance, zu ändern Zustand, je nachdem die gleiche bit in der andere operand.
OR
ist bitweise max, undAND
ist bitweise min.Sehr gut erklärt Paulo Ebermann. Schön dich hier zu sehen als auch Crypto.SE!
ich erstellte eine filter, die gehören mir, alles tagged Kryptographie, ändert sich auch die alten Fragen. Auf diese Weise fand ich hier Ihre Antwort.
InformationsquelleAutor Corey Ogburn
Wenn Sie
XOR
eine zufällige Eingabe mit einem voreingenommenen Eingabe, die Ausgabe ist zufällig. Das gleiche gilt nicht fürAND
oderOR
. Beispiel:Als @Greg Hewgill erwähnt, auch wenn beide Eingänge sind zufällig, mit
AND
oderOR
führt voreingenommenen Ausgang.Dem Grund verwenden wir
XOR
über etwas mehr Komplex ist, dass es, es gibt keine Notwendigkeit:XOR
funktioniert perfekt, und es ist unglaublich dumm-schnell.InformationsquelleAutor BlueRaja - Danny Pflughoeft
Den source-code für verschiedene Versionen von
hashCode()
im java.util.Arrays ist eine großartige Referenz für eine solide, Allgemeine Verwendung Hash-algorithmen. Sie werden leicht verstanden und übersetzt in andere Programmiersprachen.Grob gesagt, die meisten multi-Attribut
hashCode()
Implementierungen Folgen diesem Muster:Können Sie suchen, andere StackOverflow-Q&As " für mehr Informationen über die Magie hinter
31
, und warum Java-code verwendet es so oft. Es ist nicht perfekt, aber hat eine sehr gute Allgemeine performance-Eigenschaften.string
kollidiert mitstring + "AA"
IIRC), und Sie vor langer Zeit wünschten sich, Sie hatte nicht gebacken, dass der Algorithmus in der spec. Das heißt, die Verwendung einer größeren ungeraden Zahl mit mehr bits festgelegt, und das hinzufügen einer Verschiebungen oder Rotationen behebt das problem. MurmurHash3 die "Mischung" macht.InformationsquelleAutor kevinarpe
Abdeckung der linken 2 Spalten und versuchen, herauszufinden, was die Eingänge werden mit nur der Ausgabe.
Sah man ein 1-bit-sollten Sie arbeitete heraus, dass beide Eingänge waren 1.
Nun tun Sie dasselbe mit XOR
XOR gibt nichts über es-Eingänge.
InformationsquelleAutor Robert