Lassen Sie mich im Voraus entschuldigen, denn das ist etwas schwer zu verstehen ...
Zunächst einmal wissen Sie das bereits java.util.Random
nicht völlig zufällig ist. Es erzeugt Sequenzen auf perfekt vorhersehbare Weise aus dem Samen. Sie haben völlig Recht, dass der Startwert, da er nur 64 Bit lang ist, nur 2 ^ 64 verschiedene Sequenzen erzeugen kann. Wenn Sie irgendwie 64 echte Zufallsbits generieren und damit einen Startwert auswählen würden, könnten Sie diesen Startwert nicht verwenden, um zufällig zwischen allen 52 zu wählen ! mögliche Sequenzen mit gleicher Wahrscheinlichkeit.
Diese Tatsache ist jedoch ohne Bedeutung , solange Sie nicht mehr als 2 ^ 64 Sequenzen generieren, solange die 2 ^ 64 Sequenzen, die sie generieren können , nichts "Besonderes" oder "merklich Besonderes" enthalten .
Nehmen wir an, Sie hatten ein viel besseres PRNG, das 1000-Bit-Samen verwendete. Stellen Sie sich vor, Sie hätten zwei Möglichkeiten, es zu initialisieren: Eine Möglichkeit würde es mit dem gesamten Seed initialisieren und eine Möglichkeit würde den Seed vor der Initialisierung auf 64 Bit reduzieren.
Wenn Sie nicht wüssten, welcher Initialisierer welcher ist, können Sie einen Test schreiben, um sie zu unterscheiden? Es sei denn, Sie hatten das (Un-) Glück, den schlechten mit demselben zu initialisieren 64 Bit zweimal zu , lautet die Antwort nein. Sie konnten nicht zwischen den beiden Initialisierern unterscheiden, ohne detaillierte Kenntnisse über einige Schwachstellen in der spezifischen PRNG-Implementierung zu haben.
Alternativ stellen Sie sich vor, dass die Random
Klasse ein Array von 2 ^ 64 Sequenzen hatte, die zu einem bestimmten Zeitpunkt in der fernen Vergangenheit vollständig und zufällig ausgewählt wurden, und dass der Startwert nur ein Index in diesem Array war.
Die Tatsache, dass Random
nur 64 Bit für den Startwert verwendet werden, ist also nicht der Fall statistisch gesehen unbedingt ein Problem, solange keine signifikante Wahrscheinlichkeit besteht, dass Sie denselben Startwert zweimal verwenden.
Für kryptografische Zwecke reicht ein 64-Bit-Startwert natürlich nicht aus, da es rechnerisch möglich ist, ein System dazu zu bringen, denselben Startwert zweimal zu verwenden.
BEARBEITEN:
Ich sollte hinzufügen, dass, obwohl alle oben genannten Punkte korrekt sind, die tatsächliche Implementierung von java.util.Random
nicht fantastisch ist. Wenn Sie ein Kartenspiel schreiben, verwenden Sie möglicherweise die MessageDigest
API, um den SHA-256-Hash von zu generieren "MyGameName"+System.currentTimeMillis()
, und verwenden Sie diese Bits, um das Deck zu mischen. Mit dem obigen Argument müssen Sie sich keine Sorgen machen, solange Ihre Benutzer nicht wirklich spielen currentTimeMillis
. Wenn Ihre Benutzer sind wirklich Glücksspiel, dann verwenden SecureRandom
ohne Samen.
Random
sind niemals echte Zufallszahlen. Es ist ein PRNG, wobei P für "Pseudo" steht. Für echte Zufallszahlen benötigen Sie eine Zufallsquelle (z. B. random.org).