PHP_INT_MAX
hier ist 2 -1 (64-bit signed int max).
mt_rand()
verarbeitet jedoch keine so großen Werte. Der Mersenne-Twister generiert intern 32-Bit-Wörter, und PHP mt_getrandmax()
ist nur 2 -1 (es wirft das höchste Bit weg).
Um einen Wert in Ihrem Wunsch min
-max
Bereich, mt_rand
zuerst bekommen die 0 bis 2 -1 Zufallszahl zu erzeugen, skaliert es dann mit dieser Formel:
x = ((x/(mt_getrandmax() + 1)) * (max - min + 1)) + min;
(Siehe Quelle rand.c und php_rand.h.)
Grundsätzlich skaliert es blind die intern generierte Nummer, um den übergroßen Bereich zu passen, ohne sogar eine Warnung zu erhöhen. Die Multiplikation mit dem übergroßen Bereich erzeugt eine Menge von Nullen in den niedrigen Bits, und das Hinzufügen von min
(was 1 ist) macht das Ergebnis ungerade.
Das Problem ist noch dramatischer in hexadezimal, wo Sie, dass die unteren 32 Bits jeder Zahl sind vollständig nicht zufällig sehen:
for ($i = 0; $i < 10000; $i++) {
printf("%016x\n", mt_rand(1, PHP_INT_MAX));
}
Ausgang:
41e0449b00000001
53d33d7c00000001
6ec8855700000001
234140e000000001
13a4581900000001
77547beb00000001
35a0660a00000001
0d0cd44200000001
...
Es gibt eine Notiz in the manual, die versucht, davor zu warnen, obwohl es das Problem untertreibt:
Die Verteilung der Rückgabewerte mt_rand()
ist auf gerade Zahlen bei 64-Bit-Builds von PHP ausgerichtet, wenn max
über 2 hinausgeht. Dies liegt daran, dass, wenn max
größer als der von mt_getrandmax()
zurückgegebene Wert ist, der Ausgang des Zufallszahlengenerators hochskaliert werden muss.
(Sie sagt, sie zu geraden Zahlen vorbelastet sind, aber das ist nur wahr, wenn min
selbst ist.)
Wahrscheinlich im Zusammenhang mit dieser, aus [PHP-Manual Seite für mt_rand] (http: // PHP. net/manual/de/function.mt-rand.php): * Vorsicht: Die Verteilung der Rückgabewerte von mt_rand() ist auf gerade Zahlen in 64-Bit-Builds von PHP ausgerichtet, wenn max größer als 2^32 ist.Wenn max größer ist als der von mt_getrandmax() zurückgegebene Wert, muss die Ausgabe des Zufallszahlengenerators hochskaliert werden. * – Simba
Weil PHP_INT_MAX> mt_getrandmax(), [mehr Details] (https: //www.reddit. com/r/lolphp/Kommentare/3eaw98/mt_rand1_php_int_max_only_generates_odd_numbers/ctdhxha). – Sony
http://assets.amuniversal.com/321a39e06d6401301d80001dd8b71c47 – j08691