Ich bin fast sicher, dass es eine x
, für die der Xorshift Betrieb 0 zurück
Beweis:
Erstens haben wir diese Gleichungen:
a = x^(x >> 12);
b = a^(a << 25);
c = b^(b >> 27);
sie Substituieren:
b = (x^x >> 12)^((x^x >> 12) << 25);
c = b^(b >> 27) = ((x^x >> 12)^((x^x >> 12) << 25))^(((x^x >> 12)^((x^x >> 12) << 25)) >> 27);
Wie Sie sehen können, obwohl c
ist eine komplexe Gleichung, es ist perfekt abelian.
Es bedeutet, dass Sie die Bits von c
als vollständig boolesche Ausdrücke der Bits von x
ausdrücken können.
So können Sie einfach ein Gleichungssystem für die Bits b0
, b1
, b2
, konstruieren ... so:
(Anmerkung: die Koeffizienten sind nur Beispiele, ich habe sie nicht berechnen, aber so würde es aussehen):
c0 = x1^!x32^x47 ...
c1 = x23^x45^!x61 ...
...
c63 = !x13^...
Von diesem Punkt haben Sie 64 Gleichungen und 64 Unbekannten. Sie können es einfach mit Gauss-elimination lösen, Sie werden immer eine einzige einzigartige Lösung haben.
Außer einigen seltenen Fällen, d. H. Wenn die Determinante der Koeffizienten des Gleichungssystems Null ist, aber in der Größe einer solchen großen Matrix sehr unwahrscheinlich ist.
Auch wenn es passiert, es würde bedeuten, dass Sie einen Informationsverlust in jeder Iteration haben, das heißt sie können nicht alle der 2^64
möglichen Werte von x
, nur einige von ihnen bekommen.
Betrachten wir nun die viel wahrscheinlichere Möglichkeit, dass die Koeffizientenmatrix nicht Null ist. In diesem Fall haben Sie für alle möglichen 2^64
Werte von x
alle möglichen 2^64
Werte von c
, und diese sind alle unterschiedlich.
So können Sie 0 erhalten.
Erweiterung: tatsächlich erhalten Sie Null für Null ... Entschuldigung, der Beweis ist nützlicher, um zu zeigen, dass es nicht so einfach ist, wie es für den ersten Punkt scheint. Der wichtige Teil ist, dass Sie die Bits von c
als eine boolesche Funktion der Bits von x
ausdrücken können.
Es gibt ein anderes Problem mit diesem Zufallszahlengenerator. Und das ist, dass selbst wenn man irgendwie die Funktion nicht solches Problem hat ändern (zum Beispiel durch Zugabe von 1 in jeder Iteration):
Sie können immer noch nicht garantieren, dass es nicht in bekommen eine kurze Schleife * für alle möglichen Werte von x
. Was ist, wenn es eine Schleife mit 5 Längen für den Wert 345234523452345 gibt? Können Sie für alle möglichen Ausgangswerte nachweisen? Ich kann nicht.
Eigentlich mit einer wirklich Pseudo-Zufalls-Iteration-Funktion, Ihr System wird wahrscheinlich Schleife nach 2^32
Iterationen. Es hat eine fast trivial combinatoric Grund hat, aber „leider dieser Spielraum ist klein, sie zu enthalten“ ;-)
So:
- Wenn ein
2^32
Schleifenlänge für Ihre PRNG ist in Ordnung, dann verwenden eine bewährte Iterationsfunktion, die irgendwo im Netz gesammelt wurde.
- Wenn dies nicht der Fall ist, aktualisieren Sie die Bitlänge auf mindestens
2^128
. Es wird eine etwa 2^64
Loop-Länge ergeben, die nicht so schlecht ist.
- Wenn Sie weiterhin eine 64-Bit-Ausgabe wünschen, verwenden Sie intern 128-Bit-Zahlen, aber geben Sie
(x>>64)^(x&(2^64-1))
zurück (d. H. Xor-in die obere und untere Hälfte des internen Status x
).
subtrahieren nur 1 davon zu verwenden, wenn Sie 0. 'uint64_t Rand ermöglichen müssen() {return xorshift_next() - 1;} ' – immibis
Die Verwendung von Modulus ist nicht geeignet, uniforme Zufallszahlen mit * any * base PRNG zu erhalten. – GManNickG
Ich weiß über das Modulproblem (erste 'n' Werte werden wahrscheinlicher), aber es ist die einfachste/schnellste Lösung. Vorausgesetzt, es könnte ausreichen, um eins zu subtrahieren. Ich wäre immer noch an einer allgemeineren Lösung interessiert, da jemand schon darauf gestoßen sein muss. Oder wird nur eine Art Rückweisungsstichprobe verwendet? – Flamefire