Wie zufällig ist JavaScript's Math.random?

116

Seit 6 Jahren habe ich einen Zufallsgenerator auf meiner Website. Lange Zeit war es das erste oder zweite Ergebnis bei Google für "Zufallszahlengenerator" und wurde verwendet, um Dutzende, wenn nicht Hunderte von Wettbewerben und Zeichnungen in Diskussionsforen und Blogs zu entscheiden (ich weiß, weil ich die Verweise in meinem sehe Weblogs und in der Regel einen Blick darauf werfen).

Heute hat mir jemand eine E-Mail geschickt, um mir zu sagen, dass es möglicherweise nicht so zufällig ist, wie ich dachte. Sie versuchte sehr große Zufallszahlen zu generieren (z. B. zwischen 1 und 10000000000000000000) und stellte fest, dass diese fast immer die gleiche Anzahl von Ziffern hatten. In der Tat habe ich die Funktion in eine Schleife eingeschlossen, damit ich Tausende von Zahlen erzeugen konnte, und für sehr große Zahlen betrug die Variation nur etwa zwei Größenordnungen.

Warum?

Hier ist die Loop-Version, damit Sie sie selbst ausprobieren können:

http://andrew.hedges.name/experiments/random/randomness.html

Es enthält sowohl eine einfache Implementierung aus dem Mozilla Developer Network als auch Code aus dem Jahr 1997, den ich von einer nicht mehr vorhandenen Webseite entfernt habe (Paul Houles "Central Randomizer 1.3"). Zeigen Sie die Quelle an, um zu sehen, wie die einzelnen Methoden funktionieren.

Ich habe hier und anderswo über Mersenne Twister gelesen . Was mich interessiert, ist, warum es keine größeren Unterschiede in den Ergebnissen der in JavaScript integrierten Math.random- Funktion geben würde. Vielen Dank!

Andrew Hedges
quelle
"sarnath'd" wie in, bis zum Anschlag geschlagen, oder in diesem Fall die Antwort
maetl
5
Wenn Sie nach der Antwort auf die Frage im Titel suchen
Andrew B.

Antworten:

182

Gegebene Zahlen zwischen 1 und 100.

  • 9 haben 1 Stelle (1-9)
  • 90 haben 2 Ziffern (10-99)
  • 1 hat 3 Ziffern (100)

Gegebene Zahlen zwischen 1 und 1000.

  • 9 haben 1 Ziffer
  • 90 haben 2 Ziffern
  • 900 haben 3 Ziffern
  • 1 hat 4 Ziffern

und so weiter.

Wenn Sie also zufällig einige auswählen, hat die überwiegende Mehrheit der ausgewählten Zahlen die gleiche Anzahl von Ziffern, da die überwiegende Mehrheit der möglichen Werte die gleiche Anzahl von Ziffern hat.

QUentin
quelle
11
Ihre Vorstellung von Zufälligkeit, die perfekt und gleichmäßig verteilt bedeutet, ist faszinierend ...
19
@ R.Pate - Zufallszahlenerzeugung ist nicht viel , wenn es gleichmäßig auf einer langen Skala verteilt ist
annakata
3
Lies erneut. @David gibt nur an, welche Art von Zahlen zwischen den Grenzwerten liegen, nicht das Ergebnis der Auswahl von N Zufallszahlen. Ich gebe zu, dass der Titel irreführend ist.
Nikc.org
3
Für die Aufzeichnung habe ich sowohl diese als auch die Antworten von @ jwoolard abgestimmt. Ich habe diese als akzeptierte Antwort gewählt, weil die Beispiele kristallklar machen, warum die Verteilung von Zahlen auf Zahlen mit mehr Ziffern verzerrt ist.
Andrew Hedges
1
@ Andrew-Hedges ganz richtig - das ist die klarere Antwort, aber danke :)
Jwoolard
55

Ihre Ergebnisse werden tatsächlich erwartet. Wenn die Zufallszahlen gleichmäßig in einem Bereich von 1 bis 10 ^ n verteilt sind, würden Sie erwarten, dass etwa 9/10 der Zahlen n Ziffern und weitere 9/100 n-1 Ziffern haben.

Jwoolard
quelle
8
Genau. Die Verteilung der Anzahl der Ziffern wird voraussichtlich verzerrt sein. Die Verteilung des Protokolls der Anzahl der Stellen sollte jedoch einheitlich sein.
Noldorin
45

Es gibt verschiedene Arten von Zufälligkeiten. Math.random gibt Ihnen eine gleichmäßige Verteilung der Zahlen.

Wenn Sie unterschiedliche Größenordnungen wünschen, würde ich vorschlagen, eine Exponentialfunktion zu verwenden, um eine sogenannte Potenzgesetzverteilung zu erstellen :

function random_powerlaw(mini, maxi) {
    return Math.ceil(Math.exp(Math.random()*(Math.log(maxi)-Math.log(mini)))*mini)
}

Diese Funktion sollte Ihnen ungefähr die gleiche Anzahl von 1-stelligen Zahlen wie 2-stellige Zahlen und 3-stellige Zahlen geben.

Es gibt auch andere Verteilungen für Zufallszahlen wie die Normalverteilung (auch Gaußsche Verteilung genannt).

Christian
quelle
Mit diesem Algorithmus habe ich das minimum = 1und das gesetzt maximum = 10und manchmal 11 als Ergebnis erhalten. Sie wollten wahrscheinlich Math.flooranstelle vonMath.round
Sam Eaton
1
Warum funktioniert es? Wandelt es eine gleichmäßige Verteilung in eine exponentielle Verteilung um?
Shinzou
@shinzou Ich fragte auf math.stackexchange und bekam eine etwas andere Formel als Antwort. Ich habe den Code geändert, um die mathematisch abgeleitete Formel von math.stackexchange widerzuspiegeln.
Christian
20

Sieht für mich völlig zufällig aus! (Hinweis: Es ist browserabhängig.)

Persönlich denke ich, dass meine Implementierung besser wäre, obwohl ich sie XKCD gestohlen habe , der IMMER anerkannt werden sollte:

function random() {
  return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}
Arafangion
quelle
19
+1 für die Erwähnung, dass es browserabhängig ist, -1 für das Ausleihen von xkcd ohne Verknüpfung.
Erforderlich oder nicht, da es xkcd ist, wird es zugeordnet. :)
Arafangion
2
OT: Ich bin überrascht und glücklich, dass "XKCD" diese Woche die Antwort auf eine Frage der University Challenge war: D
Matt Sach
2
Bergi: Ein direkter Link ist nicht genug?
Arafangion
Ich denke, sie bedeuten, dass der Witz nicht richtig zitiert wurde ("random = 4;" anstelle von "return 4;")
Eren Tantekin
18

Im folgenden Artikel wird erläutert, wie math.random () in den wichtigsten Webbrowsern (nicht) sicher ist: "Temporäre Benutzerverfolgung in den wichtigsten Browsern und domänenübergreifende Informationslecks und Angriffe" von Amid Klein (2008) . Es ist nicht stärker als die in Java oder Windows integrierten PRNG-Funktionen.

Andererseits erfordert die Implementierung von SFMT der Periode 2 ^ 19937-1 2496 Bytes des internen Zustands, der für jede PRNG-Sequenz aufrechterhalten wird. Einige Leute können dies als unverzeihliche Kosten betrachten.

jj1bdx
quelle
1
+1: Das erwähnte Papier ist großartig, weit über das hinaus, worum es in der ursprünglichen Frage ging.
Roland Illig
5

Wenn Sie eine Zahl wie 10000000000000000000 verwenden, gehen Sie über die Genauigkeit des Datentyps hinaus, den Javascript verwendet. Beachten Sie, dass alle generierten Zahlen mit "00" enden.

Greg
quelle
1
Das ist in diesem Fall jedoch nicht sein Problem.
Joey
3
@ Johannes - es ist eines seiner Probleme :)
Annakata
Die Verteilung von IEE754 ist nicht gleichmäßig. Vielleicht können Sie 0 bis 999 in Zweierschritten darstellen und haben dafür genügend Genauigkeit, sodass Sie eine gleichmäßige Verteilung über diesen Bereich bemerken, wenn Sie die Zahl mehrmals auswählen. 10% sind zweistellig und 90% dreistellig. Wenn Sie jedoch anfangen, wirklich hohe Zahlen zu erreichen, wird das Inkrement 1 überschreiten. Möglicherweise können Sie nur von einer Billion Milliarden auf eine Billion Milliarden eintausend und nicht von einer Billion Milliarden und eins wechseln. Obwohl für kleine Zahlen / Skalen dieser Effekt vernachlässigbar bis nicht vorhanden ist. Der Skaleneffekt wird jedoch weitaus größere Auswirkungen haben.
jgmjgm
5

Ich habe JS Pseudozufallszahlengenerator für Chaos Game ausprobiert .

Mein Sierpiński-Dreieck sagt, es sei ziemlich zufällig: Fraktal

zie1ony
quelle
2
Würde es Ihnen etwas ausmachen, den Dreieckscode hier und jsfiddle / jsbin zu teilen, damit wir ihn in der Praxis für verschiedene Browser leicht überprüfen können?
Fabrício Matté
1
OK, aber gib mir ein paar Tage, weil ich Code ins Englische übersetzen muss. Jetzt ist es polnisch-englisch und ich habe viel Arbeit.
zie1ony
1
@ zie1ony ein paar tage sind vorbei.
Trusktr
1
usp :( work, work, work Link: kubaplas.vot.pl/green/fractal Der erste Parameter ist nr des Scheitelpunkts. Der zweite ist ein Schnittpunkt (von 0 bis 1) des Liniensegments. Experimentieren Sie einfach.
zie1ony
4
Link tot - vielleicht stattdessen ein Github-Repo?
Mark K Cowan
3

Wenn Sie Zahlen bis beispielsweise 1e6 generieren, erhalten Sie hoffentlich alle Zahlen mit ungefähr gleicher Wahrscheinlichkeit. Das bedeutet auch, dass Sie nur eine von zehn Chancen haben, eine Zahl mit einer Ziffer weniger zu erhalten. Eine Chance von eins zu hundert, zwei Ziffern weniger zu erhalten usw. Ich bezweifle, dass Sie bei Verwendung eines anderen RNG einen großen Unterschied feststellen werden, da Sie eine gleichmäßige Verteilung über die Zahlen haben, nicht deren Logarithmus.

Joey
quelle
0

Nicht zufällige Zahlen, die gleichmäßig von 1 bis N verteilt sind, haben dieselbe Eigenschaft. Beachten Sie, dass es (in gewissem Sinne) um Präzision geht. Bei einer gleichmäßigen Verteilung auf 0-99 (als Ganzzahlen) sind 90% der Zahlen zweistellig. Eine gleichmäßige Verteilung auf 0-999999 hat 905 ihrer Zahlen mit fünf Ziffern.

Jeder Satz von Zahlen (unter einigen nicht zu restriktiven Bedingungen) hat eine Dichte. Wenn jemand "Zufallszahlen" diskutieren möchte, sollte die Dichte dieser Zahlen angegeben werden (wie oben angegeben). Eine gemeinsame Dichte ist die einheitliche Dichte. Es gibt andere: die Exponentialdichte, die Normaldichte usw. Man muss wählen, welche Dichte relevant ist, bevor man einen Zufallszahlengenerator vorschlägt. Auch Zahlen, die von einer Dichte stammen, können oft leicht mit kariösen Mitteln in eine andere Dichte umgewandelt werden.

ttw
quelle