Comment puis-je générer des nombres entiers aléatoires entre deux variables spécifiées en JavaScript, par exemple, x = 4
et y = 8
produiraient n'importe lequel de 4, 5, 6, 7, 8
?
Vous trouverez quelques exemples sur la page [Mozilla Developer Network][1] :
/**
* 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;
}
Voici la logique derrière tout ça. C'est une simple règle de trois :
Math.random()
renvoie un Nombre
entre 0 (inclusif) et 1 (exclusif). Nous avons donc un intervalle comme celui-ci :
[0 .................................... 1)
Maintenant, nous voudrions un nombre entre min
(inclusif) et max
(exclusif) :
[0 .................................... 1)
[min .................................. max)
Nous pouvons utiliser Math.random
pour obtenir le correspondant dans l'intervalle [min, max]. Mais, d'abord, nous devons factoriser un peu le problème en soustrayant min
du deuxième intervalle :
[0 .................................... 1)
[min - min ............................ max - min)
Cela donne :
[0 .................................... 1)
[0 .................................... max - min)
Nous pouvons maintenant appliquer Math.random
et ensuite calculer le correspondant. Choisissons un nombre aléatoire :
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
Donc, pour trouver x
, nous devrions faire :
x = Math.random() * (max - min);
N'oubliez pas d'ajouter min
, afin d'obtenir un nombre dans l'intervalle [min, max] :
x = Math.random() * (max - min) + min;
C'était la première fonction de MDN. La seconde renvoie un nombre entier compris entre min
et max
, tous deux inclus.
Maintenant, pour obtenir des entiers, vous pouvez utiliser round
, ceil
ou floor
.
Vous pourriez utiliser Math.round(Math.random() * (max - min)) + min
, mais cela donne une distribution non uniforme. Les deux, min
et max
n'ont qu'environ la moitié des chances d'obtenir un résultat :
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
Si max
est exclu de l'intervalle, il a encore moins de chances d'obtenir un résultat que min
.
Avec Math.floor(Math.random() * (max - min +1)) + min
vous avez une distribution parfaitement égale.
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
Vous ne pouvez pas utiliser ceil()
et -1
dans cette équation parce que max
a maintenant un peu moins de chance d'être lancé, mais vous pouvez aussi lancer le résultat (non désiré) min-1
.
[1] : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
function getRandomizer(bottom, top) {
return function() {
return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
}
}
usage :
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.
}
ventilation :
Nous retournons une fonction (empruntée à la programmation fonctionnelle) qui, lorsqu'elle est appelée, renvoie un nombre entier aléatoire compris entre les valeurs bottom
et top
, inclusivement. Nous disons 'inclusive' ; parce que nous voulons inclure à la fois bottom et top dans la gamme des nombres qui peuvent être retournés. Ainsi, getRandomizer( 1, 6 )
renverra soit 1, 2, 3, 4, 5, ou 6.
(le bas est le nombre le plus bas, le haut est le nombre le plus grand).
Math.random() * ( 1 + top - bottom )
Math.random()
renvoie un double aléatoire entre 0 et 1, et si on le multiplie par un plus la différence entre top
et bottom
, on'obtiendra un double quelque part entre 0
et 1+b-a
.
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor
arrondit le nombre à l'entier inférieur le plus proche. Nous avons donc maintenant tous les entiers compris entre 0
et top-bottom
. Le 1 est déroutant, mais il doit être là parce que nous arrondissons toujours vers le bas, donc le nombre supérieur ne sera jamais atteint sans lui. La décimale aléatoire que nous générons doit être comprise entre 0
et (1+haut-bas)
pour que nous puissions arrondir vers le bas et obtenir un entier compris entre 0
et haut-bas
.
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
Le code de l'exemple précédent nous a donné un entier dans l'intervalle 0
et top-bottom
, donc tout ce que nous devons faire maintenant est d'ajouter bottom
à ce résultat pour obtenir un entier dans l'intervalle bottom
et top
inclus. :D
NOTE : Si vous passez une valeur non entière ou le plus grand nombre en premier, vous obtiendrez un comportement indésirable, mais à moins que quelqu'un ne le demande, je ne vais pas me plonger dans le code de vérification des arguments, car il est assez éloigné de l'intention de la question originale.
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)));
}
Pour tester cette fonction, et ses variantes, enregistrez le HTML/JavaScript ci-dessous dans un fichier et ouvrez-le avec un navigateur. Le code produira un graphique montrant la distribution d'un million d'appels de fonction. Le code enregistrera également les cas limites, de sorte que si la fonction produit une valeur supérieure à la valeur maximale ou inférieure à la valeur minimale, vous le saurez.
<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>