Funktion, die die Eingabe verbreitet

14

Ich würde gerne wissen, ob es eine Funktion von n-Bit-Zahlen bis n-Bit-Zahlen gibt, die die folgenden Eigenschaften aufweist:f

  • f sollte bijektiv sein
  • Sowohl als auch sollten ziemlich schnell berechenbar seinff1
  • f sollte eine Zahl zurückgeben, die keine signifikante Korrelation zu ihrer Eingabe aufweist.

Das Grundprinzip ist folgendes:

Ich möchte ein Programm schreiben, das mit Daten arbeitet. Einige Informationen der Daten werden in einem binären Suchbaum gespeichert, in dem der Suchschlüssel ein Symbol eines Alphabets ist. Mit der Zeit füge ich dem Alphabet weitere Symbole hinzu. Neue Symbole erhalten einfach die nächste freie Nummer. Daher wird der Baum immer eine kleine Neigung zu kleineren Schlüsseln haben, was mehr Neuausgleich bewirkt, als ich für nötig halte.

Meine Idee ist es, die Symbolzahlen mit so zu zerfleischen, dass sie über den gesamten Bereich von . Da die Symbolnummern nur bei der einmaligen Ein- und Ausgabe eine Rolle spielen, sollte die Anwendung einer solchen Funktion nicht zu teuer sein.f[0,2641]

Ich habe über eine Iteration des Xorshift-Zufallszahlengenerators nachgedacht, aber ich weiß nicht wirklich, wie ich sie rückgängig machen kann, obwohl dies theoretisch möglich sein sollte.

Kennt jemand eine solche Funktion?
Ist das eine gute Idee?

FUZxxl
quelle
1
Ich bin kein Experte, aber vielleicht können Sie eine Pseudozufalls-Permutation verwenden (siehe zum Beispiel die Feistel-Chiffre )
Vor
Wenn Sie im Wesentlichen eine Hash-Funktion berechnen, warum nicht Hashing verwenden?
Vonbrand
@vonbrand Hashing ist nicht umkehrbar. Siehe Anforderung Nummer 2.
FUZxxl
Warum muss es reversibel sein? Was ist falsch daran, es durch Nachschlagen umkehrbar zu machen?
Vonbrand
1
Sie können (f (x), x) als Schlüssel speichern.
AdrianN

Antworten:

6

Sie können nämlich Fibonacci-Hashing verwenden

.hF(k)=k512k512

Für Sie n paarweise getrennte Zahlen (ungefähr), die in [ 0 , 1 ] gleichmäßig verteilt sind . Wenn Sie auf [ 1 .. M ] skalieren und abrunden, erhalten Sie ungefähr gleichmäßig verteilte Zahlen in diesem Intervall.k=1,,nn[0,1][1..M]

Dies sind zum Beispiel skaliert auf [ 0..10000 ] (linke ursprüngliche Sequenz, rechts sortiert):hF(1),,hF(200)[0..10000]

Bildbeschreibung hier eingeben

Dies ist ein Beispiel für das, was Knuth multiplikatives Hashing nennt . Für die Wortgröße des Computers, eine ganze Zahl, die relativ zu w primiert ist, und M die Anzahl der benötigten Adressen, die wir verwendenwAwM

h(k)=M((kAw)mod1)

als hashing funktion. Das Obige folgt mit (stellen Sie sicher, dass Sie es mit einer ausreichenden Genauigkeit berechnen können). Während dies auch mit jeder anderen irrationalen Zahl außerϕ-1funktioniert, ist es eine von nur zwei Zahlen, die zu den "am gleichmäßigsten verteilten" Zahlen führen.A/w=ϕ1=512ϕ1

Mehr dazu in Die Kunst der Computerprogrammierung , Band 3 von Donald Knuth (Kapitel 6.4 ab Seite 513 in der zweiten Ausgabe). Insbesondere werden Sie feststellen, warum die resultierenden Zahlen paarweise verschieden sind (zumindest wenn ) und wie Sie die Umkehrfunktion berechnen, wenn Sie natürliches A und w anstelle von ϕ - 1 verwenden .nMAwϕ1

Raphael
quelle
1
Wie berechne effizient? f1
Freitag,
1
@frafl Ich hoffe meine Bearbeitung geht etwas auf dein Anliegen ein. Es ist jedoch klar, dass diese Hashtechniken nicht speziell dafür ausgelegt sind, effizient umkehrbar zu sein.
Raphael
Ja, ich stimme dem zu, aber ich würde es nicht als akzeptierte Antwort empfehlen.
Freitag,
1

Für Bit-Eingänge funktioniert diese Funktion:k

hash(n)=(nmod2k2)2k2+ndiv2k2

Dies ist dahingehend umkehrbar, dass ist und nicht sequentielle Paare { n , m } , n < m , wobei h a s h ( m ) < h a s ist h ( n ) . Beachten Sie, dass Ausgabe und Eingabe korrelieren können, insbesondere wenn Ihre Eingabe in { 1 , , 2 k liegthash(hash(n))=n{n,m},n<mhash(m)<hash(n).{1,,2k21}

Ref: Reversible Hash-Funktion

Reza
quelle
Das sieht einfach und schön aus. Ich werde das testen.
FUZxxl
1
1ρ
es ist ziemlich klar! für 64-Bit (0x00000000FFFFFFFF) und Sie sollten (<<) 32 Bit verschieben. Diese Funktion ist in der Praxis einfach, praktisch und schnell genug.
Reza
1
x{1,,2321}232x