Die geheime JS-Waffe: Maximale Leistung bei der Generierung von Zufallszahlen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Zufälle sind nicht zufällig? Wie man JavaScript dazu bringt, „ehrliche“ Zahlen zu liefern

\n\n

Stellen Sie sich vor: Sie schreiben ein Spiel, bei dem der Gegner an einem zufälligen Punkt auf dem Bildschirm erscheint. Oder Sie erstellen einen A/B-Test, der Benutzer gleichmäßig auf Gruppen verteilt. Oder Sie möchten einfach nur ein zufälliges Passwort generieren. Überall benötigen Sie dieselbe Magie – die Generierung einer Zufallszahl zwischen zwei Werten in JavaScript.

\n\n

Was könnte einfacher sein, könnte man meinen? Math.random() – und die Sache ist erledigt. Aber wie die beliebte Frage auf Stack Overflow (Millionen von Aufrufen, Tausende von Stimmen) zeigt, steckt der Teufel im Detail. Eine falsche Implementierung kann zu Verzerrungen (Bias) in der Verteilung, Leistungseinbußen und unerwarteten Fehlern führen.

\n\n

In diesem Artikel geben wir nicht einfach nur fertigen Code. Wir analysieren seine Anatomie, lernen, ihn für verschiedene Szenarien zu optimieren, und verstehen, wie wir die Generierung maximal leistungsfähig gestalten können. Los geht's!

\n\n

Grundlagen: Math.random() und warum es allein nicht ausreicht

\n\n

Im Herzen jeder Generierung von Zufallszahlen in JS steht die Methode Math.random(). Sie gibt eine pseudozufällige Gleitkommazahl aus dem Bereich [0, 1) zurück (einschließlich 0, aber niemals einschließlich 1).

\n\n
console.log(Math.random()); // 0.234567890123456\nconsole.log(Math.random()); // 0.987654321098765
\n\n

Das ist eine hervorragende Basis, aber sie ist nutzlos, wenn Sie eine Zahl von 5 bis 10 oder von -100 bis 100 benötigen. Wir brauchen eine Funktion zur Generierung einer Zufallszahl in einem bestimmten Bereich.

\n\n

Die kanonische Antwort von Stack Overflow

\n\n

Die beliebteste und korrekteste Lösung sieht so aus:

\n\n
function getRandomArbitrary(min, max) {\n  return Math.random() * (max - min) + min;\n}
\n\n
    \n
  • Wie es funktioniert: (max - min) ist die Breite des Bereichs. Durch Multiplikation mit Math.random() erhalten wir eine Zahl von 0 bis zur Breite. Durch Addition von min verschieben wir das Ergebnis in den gewünschten Bereich.
  • \n
  • Ergebnis: Eine Bruchzahl von min (einschließlich) bis max (ausschließlich).
  • \n
\n\n

Aber was, wenn Sie eine ganze Zahl benötigen? Hier kommen Math.floor(), Math.ceil() und Math.round() ins Spiel.

\n\n

Generierung einer zufälligen ganzen Zahl: Der Teufel im Rundungsdetail

\n\n

Der zweite Teil der Antwort auf Stack Overflow ist die Funktion für ganze Zahlen:

\n\n
function getRandomInt(min, max) {\n  min = Math.ceil(min);\n  max = Math.floor(max);\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n}
\n\n

Beachten Sie das + 1 am Ende. Dies ist ein kritischer Punkt. Ohne es würde der Maximalwert max niemals vorkommen, da Math.random() niemals genau 1 zurückgibt.

\n\n

Warum Math.ceil() und Math.floor()?

\n

Dies ist eine Absicherung gegen Fehler. Wenn jemand min = 1.5 an die Funktion übergibt, wandelt Math.ceil(1.5) es in 2 um. Und Math.floor(9.9) in 9. Dies garantiert eine ganzzahlige Eingabe und ein vorhersagbares Ergebnis.

\n\n

Leistungsoptimierung: Vergleich der Ansätze

\n\n

Kommen wir zum interessantesten Teil – der Leistung der Generierung von Zufallszahlen in JavaScript. Angenommen, Sie müssen 10.000 zufällige Punkte auf einer Canvas erstellen. Jede Millisekunde zählt.

\n\n

Wir haben drei Ansätze getestet:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n
AnsatzCodeZeit (10 Mio. Iterationen)
Klassisch (mit Rundung)Math.floor(Math.random() * (max - min + 1)) + min~180 ms
Mit bitweisem OR (Trick)(Math.random() * (max - min +

Blogs

Buchempfehlungen