Skip to content

Alles für WordPress, Webentwicklung — und mehr

🎲 Wie man eine zufällige ganze Zahl in einem Bereich mit JavaScript generiert

🎲 Wie man eine zufällige ganze Zahl in einem Bereich mit JavaScript generiert

Zufallszahlen werden überall benötigt. Bestell-IDs in Onlineshops, Reset-Codes für Passwörter, Würfelwürfe in Browserspielen, die Auswahl von Gewinnspielteilnehmern. Und fast immer schreiben Entwickler dieselbe Zeile: Math.random().

Doch zwischen „eine zufällige Dezimalzahl von 0 bis 1 erhalten" und „eine zufällige Ganzzahl von 5 bis 20 erhalten" liegt ein Abgrund aus drei Operationen, bei denen Anfänger regelmäßig Fehler machen: Math.floor und Math.ceil, plus eins oder nicht plus eins, Verwirrung, die entweder zu Bereichsüberläufen oder zu ungleichmäßiger Verteilung führt.

Lassen Sie uns die Formel bis zur letzten Klammer zerlegen, einen funktionierenden Generator in reinem HTML+CSS+JS schreiben und uns ansehen, wo Math.random() an seine Grenzen stößt.

💡 Kurzüberblick:

  • Zerlegung der Formel Math.floor(Math.random() * (max - min + 1)) + min, Verständnis jeder einzelnen Operation.
  • Erfahren, warum nur Math.floor funktioniert, nicht Math.ceil oder Math.round, mit Beispielen für Bereichsverzerrungen.
  • Kopieren eines fertigen HTML-Generators: zwei Felder, ein Button, Ergebnisausgabe, reines JS, keine Frameworks.
  • Beherrschung von Crypto.getRandomValues, wenn Math.random nicht geeignet ist und Sie eine kryptografisch sichere Alternative benötigen.

Wie Math.random() funktioniert

Math.random() ist eine statische Methode des eingebauten Math-Objekts. Sie nimmt keine Argumente entgegen und gibt eine pseudozufällige Gleitkommazahl im Bereich [0, 1) zurück, gemäß der MDN-Spezifikation. Die eckige Klammer bei null bedeutet „einschließlich", die runde Klammer bei eins bedeutet „ausschließlich". Sie können also 0.0, einen Wert um 0.372 oder etwas nahe 0.999 erhalten, aber Sie werden niemals exakt 1.0 bekommen.

Die Verteilung ist annähernd gleichmäßig. Die Implementierung ist in der Engine (V8, SpiderMonkey, JavaScriptCore) eingebaut, und der Entwickler kann den spezifischen Algorithmus (meist xorshift128+) weder wählen noch zurücksetzen; der Startwert wird von der Engine beim Start gesetzt.

Für sich allein ist Math.random() für praktische Aufgaben nutzlos. Spiele brauchen Ganzzahlen, Lotterien brauchen Ganzzahlen innerhalb eines Bereichs, Kryptografie braucht kryptografisch sichere Entropie, die Math.random() nicht bietet. Deshalb wird immer eine Bereichsumrechnungsformel darumgelegt.

Die Formel: Zufällige Ganzzahl im Bereich [min, max]

Die grundlegende Formel, die die allermeisten Fälle in der Webentwicklung abdeckt:

1function randomInt(min, max) {
2 return Math.floor(Math.random() * (max - min + 1)) + min;
3}

Zerlegen wir sie anhand eines Lernbeispiels mit min = 5 und max = 10, basierend auf der Math.random-Dokumentation:

  • Angenommen, Math.random() gab einen Wert R im Bereich [0, 1) zurück.
  • max - min + 1 = 10 - 5 + 1 = 6, die Anzahl der möglichen ganzzahligen Ergebnisse: 5, 6, 7, 8, 9, 10.
  • R * 6 skalierte die zufällige Dezimalzahl auf die Breite des Bereichs.
  • Math.floor(R * 6) rundete ab, indem der Nachkommateil verworfen wurde. Nun haben wir einen Index von 0 bis 5.
  • index + min verschob um min. Fertig: eine zufällige Ganzzahl von 5 bis einschließlich 10.

Dieselbe Formel als Einzeiler:

1const roll = Math.floor(Math.random() * (max - min + 1)) + min;

Warum Math.floor, nicht Math.ceil oder Math.round

Die Wahl der Rundungsmethode beeinflusst die Verteilung entscheidend. Lassen Sie uns dies anhand eines Lernbeispiels mit dem Bereich von 1 bis 3 demonstrieren (alle Werte außer den Intervallgrenzen sind berechnet). Der Ansatz ist in der kanonischen StackOverflow-Antwort beschrieben.

Mit Math.floor und der Formel (max - min + 1):

  • Fällt Math.random() in das erste Drittel des Bereichs [0, 1): Multiplikation mit 3 ergibt einen Wert von 0 bis fast 1, Math.floor verwirft den Nachkommateil, erzeugt Index 0, plus min ergibt 1 (exakt ein Drittel der Fälle).
  • Liegt Math.random() im mittleren Drittel: Multiplikation mit 3 ergibt von 1 bis fast 2, Math.floor → Index 1, plus min2 (ein weiteres Drittel).
  • Liegt Math.random() im letzten Drittel: Multiplikation mit 3 ergibt von 2 bis fast 3, Math.floor → Index 2, plus min3 (das letzte Drittel).

Gleichmäßige Verteilung.

Was passiert mit Math.ceil? Math.ceil(Math.random() * 3) ergibt 1, 2, 3, aber 1 hat eine verschwindend geringe Chance (nur wenn Math.random() exakt 0 ist, was fast nie vorkommt). Randwerte werden verzerrt.

Math.round ist ebenfalls ungleichmäßig: Randwerte erhalten die halbe Chance im Vergleich zu mittleren Werten. Deshalb verwendet die Ganzzahl-Zufallsgenerierung ausschließlich Math.floor.

Vollständiges Beispiel: Generator in HTML, CSS und JavaScript

Eine funktionierende Seite, die Sie als .html speichern und im Browser öffnen können. Zwei Eingabefelder, ein Button, Ergebnis auf grünem Hintergrund.

1<!DOCTYPE html>
2<html lang="ru">
3<head>
4 <meta charset="UTF-8">
5 <title>Генератор случайных чисел</title>
6 <style>
7 body {
8 font-family: system-ui, sans-serif;
9 max-width: 400px;
10 margin: 50px auto;
11 padding: 0 16px;
12 }
13 label {
14 display: block;
15 margin-top: 12px;
16 font-weight: 600;
17 }
18 input {
19 width: 100%;
20 padding: 8px;
21 margin-top: 4px;
22 font-size: 16px;
23 box-sizing: border-box;
24 }
25 button {
26 margin-top: 16px;
27 padding: 10px 24px;
28 font-size: 16px;
29 cursor: pointer;
30 }
31 .result {
32 margin-top: 20px;
33 font-size: 24px;
34 font-weight: 700;
35 color: #2e7d32;
36 }
37 </style>
38</head>
39<body>
40
41 <h1>Случайное число в диапазоне</h1>
42
43 <label for="minInput">От:</label>
44 <input type="number" id="minInput" value="1">
45
46 <label for="maxInput">До:</label>
47 <input type="number" id="maxInput" value="100">
48
49 <button id="generateBtn">Сгенерировать</button>
50
51 <div class="result" id="resultDisplay"></div>
52
53 <script>
54 function randomInt(min, max) {
55 return Math.floor(Math.random() * (max - min + 1)) + min;
56 }
57
58 const minInput = document.getElementById('minInput');
59 const maxInput = document.getElementById('maxInput');
60 const generateBtn = document.getElementById('generateBtn');
61 const resultDisplay = document.getElementById('resultDisplay');
62
63 generateBtn.addEventListener('click', () => {
64 const min = parseInt(minInput.value, 10);
65 const max = parseInt(maxInput.value, 10);
66
67 if (isNaN(min) || isNaN(max)) {
68 resultDisplay.textContent = 'Введите оба числа';
69 return;
70 }
71 if (min > max) {
72 resultDisplay.textContent = '«От» не может быть больше «До»';
73 return;
74 }
75
76 const result = randomInt(min, max);
77 resultDisplay.textContent = `Результат: ${result}`;
78 });
79 </script>
80
81</body>
82</html>

Der Code ist bewusst in reinem JavaScript geschrieben, ohne Frameworks oder Bundler, sodass er ohne npm install kopiert und sofort ausgeführt werden kann. Die Funktion randomInt nimmt min und max entgegen und gibt eine Ganzzahl zurück, die beide Enden einschließt. Der Button-Handler liest die Werte aus den Feldern, validiert sie und zeigt das Ergebnis an.

Wenn Math.random() nicht ausreicht: Crypto.getRandomValues()

Math.random() ist ein Pseudozufallsgenerator. Er genügt für Spiele, Animationen, A/B-Tests und die Auswahl eines zufälligen Array-Elements. Für Aufgaben jedoch, bei denen Vorhersagbarkeit eine Verwundbarkeit bedeutet, ist er nicht geeignet: Passwort-Reset-Tokens, API-Schlüssel, kryptografische Nonces, Generatoren für Einmallinks.

Stellen Sie sich vor: Sie senden einem Nutzer einen Passwort-Reset-Link mit einem Token, der via Math.random() generiert wurde. Kennt ein Angreifer den Startwert und den Algorithmus (die für die Engine standard sind), kann er die Sequenz rekonstruieren und das Token erraten. Genau deshalb muss jeder sicherheitsrelevante Code eine kryptografisch sichere Zufallsquelle verwenden.

Für solche Szenarien existiert die Web Crypto API: crypto.getRandomValues(). Sie nutzt die kryptografisch sichere Entropiequelle des Betriebssystems und füllt das übergebene typisierte Array mit Zufallswerten.

Erzeugung einer kryptografisch sicheren zufälligen Ganzzahl in einem Bereich:

1function secureRandomInt(min, max) {
2 const range = max - min + 1;
3 const maxSafeVal = Math.floor(256 ** 4 / range) * range;
4 const buffer = new Uint32Array(1);
5
6 do {
7 crypto.getRandomValues(buffer);
8 } while (buffer[0] >= maxSafeVal);
9
10 return min + (buffer[0] % range);
11}

Dies verwendet Rejection Sampling: Die Funktion fordert einen zufälligen 32-Bit-Wert an und verwirft jene, die außerhalb des gleichmäßig teilbaren Bereichs liegen. Dies beseitigt den Modulo-Bias, bei dem manche Werte häufiger vorkommen als andere.

In der Praxis genügt Math.random() für die meisten Webanwendungen. Wenn Sie jedoch einen Generator für Einmallinks oder Bestätigungscodes schreiben, verwenden Sie crypto.getRandomValues().

Video: Eine Zufallszahl in JavaScript generieren

Eine kurze Demonstration vom Kanal dcode, die Math.random() und die Bereichsformel mit einem Live-Beispiel in der Browser-Konsole zerlegt:

⁉️🤔 Häufig gestellte Fragen

Schließt die Formel Math.floor(Math.random() * (max - min + 1)) + min die obere Grenze ein?

Ja, das tut sie. max - min + 1 ergibt die Anzahl der möglichen ganzzahligen Ergebnisse, und Math.floor in Kombination mit + min stellt sicher, dass max erreichbar ist. Mit min=1, max=3 erhalten Sie zum Beispiel 1, 2 oder 3; alle drei Werte sind möglich.

Kann man Math.ceil anstelle von Math.floor verwenden?

Technisch ja, aber die Verteilung wird ungleichmäßig. Bei Math.ceil(Math.random() * range) tritt der Wert min nur dann auf, wenn Math.random() exakt 0 zurückgibt, ein verschwindend seltenes Ereignis. Math.floor gibt jeder Ganzzahl im Bereich eine gleiche Chance, weshalb die Standardformel es verwendet.

Ist Math.random() eine echte Zufallszahl?

Nein, es ist eine Pseudozufallszahl. Die JavaScript-Engine verwendet einen deterministischen Algorithmus (meist xorshift128+), der eine statistisch gleichmäßige Sequenz erzeugt, aber die Kenntnis des Startwerts erlaubt die Vorhersage aller nachfolgenden Werte. Für Kryptografie ist dies inakzeptabel; verwenden Sie crypto.getRandomValues().

Wie generiert man eine zufällige Gleitkommazahl in einem Bereich?

Entfernen Sie Math.floor und + 1: Math.random() * (max - min) + min. Dies ergibt eine Dezimalzahl von min einschließlich bis max ausschließlich. Wenn Sie das obere Ende ebenfalls einschließen müssen, ersetzen Sie max - min durch max - min + Number.EPSILON, aber in der Praxis erfordern Dezimalbereiche selten die Inklusivität der oberen Grenze.

Was ist schneller: Math.random() oder crypto.getRandomValues()?

Math.random() ist um Größenordnungen schneller. In V8-Benchmarks erreicht der Unterschied das Hundertfache oder mehr, weil crypto.getRandomValues() einen Systemaufruf an /dev/urandom (Linux) oder Äquivalent tätigt, während Math.random() ein rein prozessinterner PRNG ist. Für die Generierung tausender Werte in einer Schleife verwenden Sie Math.random(); für ein einzelnes Sicherheits-Token verwenden Sie crypto.getRandomValues().

Zufallszahl in 30 Sekunden: Was man sich merken muss

Das Arbeitspferd ist Math.floor(Math.random() * (max - min + 1)) + min. Merken Sie sich drei Regeln: immer Math.floor (nicht ceil, nicht round), immer + 1 im Multiplikator (damit max erreichbar ist), immer + min am Ende (um den Bereich zu verschieben). Diese drei Operationen decken alles ab, vom Würfelwurf bis zur Auswahl eines zufälligen Gewinners.

Für Passwort-Reset-Codes und Tokens verwenden Sie crypto.getRandomValues(). Langsamer, aber kryptografisch sicher.

Wenn Sie es einfach ausprobieren möchten, kopieren Sie das obige HTML-Beispiel, speichern Sie es als Datei und öffnen Sie es in einem Browser. Keine Abhängigkeiten, keine Bundler. Funktioniert überall, wo es ein <script> gibt.