2016-08-04 17 views
1

Wird der folgende generierte Hash für unterschiedliche Schlüssel immer unterschiedlich sein, wenn angenommen wird, dass die Hash-Integer niemals überflogen wird? Der Schlüssel soll ASCII-codierte Zeichen enthalten.Ist diese Hash-Funktion einzigartig?

Ich denke das ist der Fall, da ich nicht an einen Ausnahmefall denken kann.

char[] arr = "abcd" 
int hash = 0 
for (int i=0; i<arr.size; i++) { 
    hash += (i+1) * arr[i] 
} 

EDIT1: Während der folgende sind technisch richtige Antworten auf meine ursprüngliche Frage, sollte ich erwähnt habe, dass die Domäne des Schlüssels, dass der gültigen E-Mail-IDs ist. Daher sind einige Ascii-Zeichen nicht enthalten. Trotzdem werde ich einige Tests durchführen und berichten. Das einzige Problem ist die Aufzählung aller Dauerwellen ist nur bis zu einer geringen Länge möglich.

Wie auch immer, meine Anforderung besteht darin, eindeutige IDs basierend auf E-Mail-IDs zu erstellen und sie als Primärschlüssel in einer Datenbank zu verwenden. Ich möchte einfach nicht die Mail-IDs selbst verwenden.

EDIT2: Okay, anscheinend gibt es viele Kollisionen. für z.B. Hash [email protected] == hash of [email protected]

... 
040 == 012 
041 == 013 
042 == 014 
043 == 015 
044 == 016 
045 == 017 
046 == 018 
047 == 019 
048 == 01: 
... 

Ich brauche einen anderen Hashing-Algorithmus. Kannst du irgendwas vorschlagen?

+0

"Wird der folgende generierte Hash für verschiedene Schlüssel immer unterschiedlich sein?" Mit der Definition von "Hash-Funktion" lautet die Antwort "Nein". Wenn die Antwort "Ja" ist - nennen Sie es nicht eine Hash-Funktion. –

+0

Sie nehmen einen großen Wert-Raum und "komprimieren" es auf einen kleineren Raum. definitionsgemäß gibt es mindestens 2 Eingabewerte, die auf den gleichen Ausgang abgebildet werden. –

+0

Es sollte mindestens eine Kollision geben – xdevs23

Antwort

4

Nein: 1 * 2 + 2 * 2 = 1 * 4 + 2 * 1 zum Beispiel.

(char[] arr = {'\u0002','\u0002'} und char[] arr = {'\u0004','\u0001'})

3

Diese beiden Strings würde identisch Hashes erzeugen:

"~ " 
"@?" 

Die oben bestehen ausschließlich aus druckbaren ASCII-Zeichen.

Eine brutale Art des Testens Ihres Algorithmus wäre einfach, alle Kombinationen von 2 Zeichen zu versuchen, dann vielleicht alle Kombinationen von 3 oder 4 Zeichen, um eine Vorstellung von der Einzigartigkeit zu bekommen.

char key[5] = {0}; 
bool used[65536] = {0}; 
for (key[0] = " "; key[0] < 128; key[0]++) 
    for (key[1] = " "; key[1] < 128; key[1]++) { 
     if (used[hashcode(key)]) { 
      printf("failed %s", key); 
     else 
      used[hashcode(key) = true; 
     } 
+0

Die beiden Werte, die Sie erwähnten, ergeben 190 bzw. 253. – DebD

+0

Ups, sorry @DebD.Ich denke es sollte –

+0

Guter Fang, @DebD sein. Mein Nachteil, dass ich die ASCII-Tabelle vor der Eingabe nicht sorgfältig geprüft habe, muss einen oktalen Wert oder etwas gelesen haben. Ich werde versuchen, den zweiten zu "@?" anstelle des falschen "{A" –

0

beantwortet Ihre weitere Frage in Ihrem bearbeiten zu suchen, um Ihre Hash-Funktion zu verbessern, eine kleine Änderung, die Sie die einzelne Zeichen durch eine Primzahl zu multiplizieren machen könnten, wäre, bevor sie den Gesamt hinzufügen. Dies garantiert keine Kollisionen, sollte aber auf sie reduziert werden, da jeder neue Ausdruck, den Sie hinzufügen, mehr und mehr ein Vielfaches von einem Strich sein wird. Ich überspringe die ersten paar Primzahlen, um einen besseren Abstand zu erhalten, also multipliziere vielleicht das erste Zeichen mit 11, das zweite mit 13, das dritte mit 17, das vierte mit 19 und so weiter. Wenn Ihre Zeichenfolgen nicht zu lang sind, brauchen Sie keine sehr große Tabelle von Primzahlen.

Wenn Sie wirklich Lust bekommen wollten, könnten Sie in die Generierung eines CRC schauen, oder verwenden Sie eine lineare Feedback-Shift-Register-Technik, um eine Signatur zu generieren. Im letzteren Fall würden Sie das neue Zeichen (oder ausgewählte Bits des neuen Zeichens) in die untersten 8 Bits der laufenden Summe XOR-XOR setzen und dann die gesamte Summe um eine Anzahl von Bits drehen.