Wie kann ich zufällige ganze Zahlen zwischen zwei angegebenen Variablen in JavaScript generieren, z. B. "x = 4" und "y = 8" würde eine der Zahlen "4, 5, 6, 7, 8" ausgeben?
Einige Beispiele finden Sie auf der Seite Mozilla Developer Network:
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Here's the logic behind it. Es'ist eine einfache Regel der Drei:
Math.random()
gibt eine Zahl
zwischen 0 (einschließlich) und 1 (ausschließlich) zurück. Wir haben also ein Intervall wie dieses:
[0 .................................... 1)
Nun möchten wir eine Zahl zwischen min
(einschließlich) und max
(ausschließlich):
[0 .................................... 1)
[min .................................. max)
Wir können Math.random
verwenden, um die entsprechende Zahl im Intervall [min, max] zu erhalten. Aber zuerst sollten wir das Problem ein wenig faktorisieren, indem wir min
vom zweiten Intervall subtrahieren:
[0 .................................... 1)
[min - min ............................ max - min)
Dies ergibt:
[0 .................................... 1)
[0 .................................... max - min)
Wir können nun Math.random
anwenden und dann den entsprechenden Wert berechnen. Wählen wir eine Zufallszahl:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
Um also x
zu finden, müssten wir folgendes tun:
x = Math.random() * (max - min);
Vergiss nicht, min
wieder hinzuzufügen, so dass wir eine Zahl im Intervall [min, max] erhalten:
x = Math.random() * (max - min) + min;
Das war die erste Funktion aus MDN. Die zweite gibt eine ganze Zahl zwischen min
und max
zurück, beide inklusive.
Um nun ganze Zahlen zu erhalten, könnte man round
, ceil
oder floor
verwenden.
Man könnte Math.round(Math.random() * (max - min)) + min" verwenden, dies ergibt jedoch eine ungleichmäßige Verteilung. Sowohl
minals auch
max` haben nur etwa die Hälfte der Chance zu würfeln:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
Schließt man max
aus dem Intervall aus, so ist die Chance zu würfeln noch geringer als bei min
.
Mit Math.floor(Math.random() * (max - min +1)) + min
erhält man eine vollkommen gleichmäßige Verteilung.
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
Du kannst ceil()
und -1
in dieser Gleichung nicht verwenden, weil max
jetzt eine etwas geringere Chance hatte zu würfeln, aber du kannst das (unerwünschte) min-1
Ergebnis auch würfeln.
function getRandomizer(bottom, top) {
return function() {
return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
}
}
Verwendung:
var rollDie = getRandomizer( 1, 6 );
var results = ""
for ( var i = 0; i<1000; i++ ) {
results += rollDie() + " "; //make a string filled with 1000 random numbers in the range 1-6.
}
Aufschlüsselung:
Wir geben eine Funktion zurück (in Anlehnung an die funktionale Programmierung), die, wenn sie aufgerufen wird, eine zufällige ganze Zahl zwischen den Werten "unten" und "oben", einschließlich, zurückgibt. Wir sagen 'inklusive', weil wir sowohl unten als auch oben in den Bereich der Zahlen, die zurückgegeben werden können, aufnehmen wollen. Auf diese Weise wird getRandomizer( 1, 6 )
entweder 1, 2, 3, 4, 5 oder 6 zurückgeben.
(unten ist die kleinere Zahl, oben ist die größere Zahl)
Math.random() * ( 1 + top - bottom )
Math.random()` gibt einen zufälligen Double zwischen 0 und 1 zurück, und wenn wir ihn mit eins plus der Differenz zwischen "oben" und "unten" multiplizieren, erhalten wir einen Double irgendwo zwischen "0" und "1+b-a".
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor" rundet die Zahl auf die nächste ganze Zahl ab. So haben wir jetzt alle ganzen Zahlen zwischen "0" und "oben-unten". Die 1 sieht verwirrend aus, aber sie muss da sein, weil wir immer abrunden, so dass die obere Zahl ohne sie nie erreicht wird. Die zufällige Dezimalzahl, die wir erzeugen, muss im Bereich von 0
bis (1+oben-unten)
liegen, damit wir abrunden können und einen Wert im Bereich von 0
bis oben-unten
erhalten.
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
Der Code im vorigen Beispiel lieferte uns eine ganze Zahl im Bereich "0" und "oben-unten", also müssen wir jetzt nur noch "unten" zu diesem Ergebnis hinzufügen, um eine ganze Zahl im Bereich "unten" und "oben" zu erhalten :D
HINWEIS: Wenn Sie einen nicht-ganzzahligen Wert oder die größere Zahl zuerst eingeben, erhalten Sie ein unerwünschtes Verhalten, aber wenn niemand danach fragt, werde ich mich nicht mit dem Code zur Überprüfung der Argumente befassen, da er ziemlich weit von der Absicht der ursprünglichen Frage entfernt ist.
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
Um diese Funktion und Variationen dieser Funktion zu testen, speichern Sie das folgende HTML/JavaScript in einer Datei und öffnen Sie es mit einem Browser. Der Code erzeugt einen Graphen, der die Verteilung von einer Million Funktionsaufrufen zeigt. Der Code zeichnet auch die Grenzfälle auf, d. h. wenn die Funktion einen Wert erzeugt, der größer als der Maximalwert oder kleiner als der Minimalwert ist, werden Sie darüber informiert.
<html>
<head>
<script type="text/javascript">
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
var min = -5;
var max = 5;
var array = new Array();
for(var i = 0; i <= (max - min) + 2; i++) {
array.push(0);
}
for(var i = 0; i < 1000000; i++) {
var random = getRandomInt(min, max);
array[random - min + 1]++;
}
var maxSample = 0;
for(var i = 0; i < max - min; i++) {
maxSample = Math.max(maxSample, array[i]);
}
//create a bar graph to show the sample distribution
var maxHeight = 500;
for(var i = 0; i <= (max - min) + 2; i++) {
var sampleHeight = (array[i]/maxSample) * maxHeight;
document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px"> [' + (i + min - 1) + ']: '+array[i]+'</span> ');
}
document.write('<hr/>');
</script>
</head>
<body>
</body>
</html>