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
afficheraient l'un des 4, 5, 6, 7, 8
?
Il y a quelques exemples sur la page 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;
}
Voici la logique derrière cela. C'est une simple règle de trois:
Math.random()
renvoie un Number
compris entre 0 (inclus) et 1 (exclusif). Nous avons donc un intervalle comme celui-ci:
[0 .................................... 1)
Maintenant, nous aimerions un nombre compris entre min
(inclus) et max
(exclusif):
[0 .................................... 1)
[min .................................. max)
Nous pouvons utiliser le Math.random
pour obtenir le correspondant dans l'intervalle [min, max). Mais, tout d’abord, considérons 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
, puis calculer le correspondant. Choisissons un nombre aléatoire:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
Donc, pour trouver x
, nous ferions:
x = Math.random() * (max - min);
N'oubliez pas d'ajouter min
back afin d'obtenir un nombre compris dans l'intervalle [min, max):
x = Math.random() * (max - min) + min;
C'était la première fonction de MDN. La seconde retourne un entier compris entre min
et max
, les deux inclusivement.
Maintenant, pour obtenir des nombres entiers, vous pouvez utiliser round
, ceil
ou floor
.
Vous pouvez utiliser Math.round(Math.random() * (max - min)) + min
, mais cela donne une distribution inégale. min
et max
ont à peu près la moitié des chances de lancer:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
Avec max
exclu de l'intervalle, il a encore moins de chance de rouler que min
.
Avec Math.floor(Math.random() * (max - min +1)) + min
vous avez une distribution parfaitement uniforme.
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, car max
avait désormais un peu moins de chances de lancer, mais vous pouvez également obtenir le résultat (non désiré) min-1
.
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
De la documentation Mozilla Developer Network:
// Returns a random integer between min (include) and max (include)
Math.floor(Math.random() * (max - min + 1)) + min;
Exemples utiles:
// 0 - 10
Math.floor(Math.random() * 11);
// 1 - 10
Math.floor(Math.random() * 10) + 1;
// 5 - 20
Math.floor(Math.random() * 16) + 5;
// -10 - (-2)
Math.floor(Math.random() * 9) - 10;
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.
}
panne:
Nous retournons une fonction (empruntée à la programmation fonctionnelle) qui, lorsqu'elle est appelée, renverra un entier aléatoire entre les valeurs bottom
et top
, inclus. Nous disons "inclusif" parce que nous voulons inclure à la fois le haut et le bas dans la plage de nombres pouvant être renvoyés. De cette façon, getRandomizer( 1, 6 )
renverra 1, 2, 3, 4, 5 ou 6.
(en bas est le nombre inférieur, en haut est le plus grand nombre)
Math.random() * ( 1 + top - bottom )
Math.random()
renvoie un double aléatoire entre 0 et 1, et si nous le multiplions par un plus la différence entre top
et bottom
, nous aurons un double quelque part entre 0
et 1+b-a
.
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor
arrondit le nombre au nombre entier le plus proche. Nous avons donc maintenant tous les entiers compris entre 0
et top-bottom
. Le 1 semble déroutant, mais il doit être présent car nous arrondissons toujours vers le bas, de sorte que le nombre le plus élevé ne sera jamais atteint sans lui. La décimale aléatoire que nous générons doit se situer dans la plage 0
à (1+top-bottom)
afin que nous puissions arrondir et obtenir un int dans la plage 0
à top-bottom
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
Le code de l'exemple précédent nous a donné un entier compris entre 0
et top-bottom
, il ne reste donc plus qu'à ajouter bottom
à ce résultat pour obtenir un entier compris dans l'intervalle bottom
et top
inclus. :RÉ
REMARQUE: Si vous transmettez d'abord une valeur non-entière ou le plus grand nombre, 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 d'arguments car il est assez éloigné de l'intention de la question d'origine. .
Retourne un nombre aléatoire compris entre 1 et 10:
Math.floor((Math.random()*10) + 1);
Retourne un nombre aléatoire compris entre 1 et 100:
Math.floor((Math.random()*100) + 1)
function randomRange(min, max) {
return ~~(Math.random() * (max - min + 1)) + min
}
Alternative si vous utilisez nderscore.js, vous pouvez utiliser
_.random(min, max)
Si vous avez besoin de variables entre 0 et max, vous pouvez utiliser:
Math.floor(Math.random() * max);
Les autres réponses ne tiennent pas compte des paramètres parfaitement raisonnables de 0
et 1
. À la place, vous devriez utiliser la round
à la place de ceil
ou floor
:
function randomNumber(minimum, maximum){
return Math.round( Math.random() * (maximum - minimum) + minimum);
}
console.log(randomNumber(0,1)); # 0 1 1 0 1 0
console.log(randomNumber(5,6)); # 5 6 6 5 5 6
console.log(randomNumber(3,-1)); # 1 3 1 -1 -1 -1
Après avoir généré un nombre aléatoire à l'aide d'un programme informatique, il est toujours considéré comme un nombre aléatoire si le nombre choisi est une partie ou la totalité du nombre initial. Mais si cela a été changé, alors les mathématiciens ne l'acceptent pas comme un nombre aléatoire et peuvent l'appeler un nombre biaisé. Mais si vous développez un programme pour une tâche simple, ce ne sera pas un cas à envisager. Mais si vous développez un programme pour générer un nombre aléatoire pour un contenu précieux tel qu'un programme de loterie ou un jeu de hasard, votre programme sera rejeté par la direction si vous n'êtes pas attentif au cas ci-dessus. =
Donc, pour ce genre de personnes, voici ma suggestion:
Générez un nombre aléatoire en utilisant Math.random()
. (Dites ceci n
)
Now for [0,10) ==> n*10 (i.e. one digit) and for[10,100) ==> n*100 (i.e. two digits) and so on. Here squire bracket indicates that boundary is inclusive and round bracket indicates boundary is exclusive.
Then remove the rest after the decimal point. (i.e. get floor) - using Math.floor(), this can be done.
Si vous savez lire une table de nombres aléatoires pour choisir un nombre aléatoire, vous savez que le processus ci-dessus (en multipliant par 1, 10, 100, etc.) n’enfreint pas celui qui m’a été mentionné au début (car il ne change que le place du point décimal.)
Étudiez l'exemple suivant et développez-le selon vos besoins.
Si vous avez besoin d'un échantillon [0,9], alors plancher de n * 10 est votre réponse et si besoin [0,99], alors plancher de n * 100 est votre réponse, etc.
Maintenant, laissez entrer votre rôle:
Vous avez demandé des nombres dans une plage spécifique. (Dans ce cas, vous êtes biaisé dans cet intervalle. - En prenant un nombre de [1,6] en lançant un dé, vous êtes alors biaisé en [1,6] mais c'est quand même un hasard si et seulement si le dé est non biaisé .)
Alors considérez votre plage ==> [78, 247] nombre d'éléments de la plage = 247 - 78 + 1 = 170; (puisque les deux limites sont inclusives.
/*Mthod 1:*/
var i = 78, j = 247, k = 170, a = [], b = [], c, d, e, f, l = 0;
for(; i <= j; i++){ a.Push(i); }
while(l < 170){
c = Math.random()*100; c = Math.floor(c);
d = Math.random()*100; d = Math.floor(d);
b.Push(a[c]); e = c + d;
if((b.length != k) && (e < k)){ b.Push(a[e]); }
l = b.length;
}
console.log('Method 1:');
console.log(b);
/*Method 2:*/
var a, b, c, d = [], l = 0;
while(l < 170){
a = Math.random()*100; a = Math.floor(a);
b = Math.random()*100; b = Math.floor(b);
c = a + b;
if(c <= 247 || c >= 78){ d.Push(c); }else{ d.Push(a); }
l = d.length;
}
console.log('Method 2:');
console.log(d);
Remarque: Dans la première méthode, j'ai d'abord créé un tableau contenant les nombres dont vous avez besoin, puis les ai placés aléatoirement dans un autre tableau. Dans la deuxième méthode, générez des nombres de manière aléatoire et vérifiez qu'ils se trouvent dans la plage dont vous avez besoin. Puis mettez-le dans un tableau. Ici, j'ai généré deux nombres aléatoires et en ai utilisé le total pour maximiser la vitesse du programme en minimisant le taux d'échec en obtenant un nombre utile. Cependant, l'ajout de nombres générés donnera également un peu de bonté. Je recommanderais donc ma première méthode pour générer des nombres aléatoires dans une plage spécifique.
Dans les deux méthodes, votre console affichera le résultat (appuyez sur f12 dans Chrome pour ouvrir la console).
Voici l'implémentation MS DotNet de la classe Random en javascript-
var Random = (function () {
function Random(Seed) {
if (!Seed) {
Seed = this.milliseconds();
}
this.SeedArray = [];
for (var i = 0; i < 56; i++)
this.SeedArray.Push(0);
var num = (Seed == -2147483648) ? 2147483647 : Math.abs(Seed);
var num2 = 161803398 - num;
this.SeedArray[55] = num2;
var num3 = 1;
for (var i_1 = 1; i_1 < 55; i_1++) {
var num4 = 21 * i_1 % 55;
this.SeedArray[num4] = num3;
num3 = num2 - num3;
if (num3 < 0) {
num3 += 2147483647;
}
num2 = this.SeedArray[num4];
}
for (var j = 1; j < 5; j++) {
for (var k = 1; k < 56; k++) {
this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55];
if (this.SeedArray[k] < 0) {
this.SeedArray[k] += 2147483647;
}
}
}
this.inext = 0;
this.inextp = 21;
Seed = 1;
}
Random.prototype.milliseconds = function () {
var str = new Date().valueOf().toString();
return parseInt(str.substr(str.length - 6));
};
Random.prototype.InternalSample = function () {
var num = this.inext;
var num2 = this.inextp;
if (++num >= 56) {
num = 1;
}
if (++num2 >= 56) {
num2 = 1;
}
var num3 = this.SeedArray[num] - this.SeedArray[num2];
if (num3 == 2147483647) {
num3--;
}
if (num3 < 0) {
num3 += 2147483647;
}
this.SeedArray[num] = num3;
this.inext = num;
this.inextp = num2;
return num3;
};
Random.prototype.Sample = function () {
return this.InternalSample() * 4.6566128752457969E-10;
};
Random.prototype.GetSampleForLargeRange = function () {
var num = this.InternalSample();
var flag = this.InternalSample() % 2 == 0;
if (flag) {
num = -num;
}
var num2 = num;
num2 += 2147483646.0;
return num2 / 4294967293.0;
};
Random.prototype.Next = function (minValue, maxValue) {
if (!minValue && !maxValue)
return this.InternalSample();
var num = maxValue - minValue;
if (num <= 2147483647) {
return parseInt((this.Sample() * num + minValue).toFixed(0));
}
return this.GetSampleForLargeRange() * num + minValue;
};
Random.prototype.NextDouble = function () {
return this.Sample();
};
Random.prototype.NextBytes = function (buffer) {
for (var i = 0; i < buffer.length; i++) {
buffer[i] = this.InternalSample() % 256;
}
};
return Random;
}());
tilisez:
var r = new Random();
var nextInt = r.Next(1, 100); //returns an integer between range
var nextDbl = r.NextDouble(); //returns a random decimal
Pour un entier aléatoire avec une plage, essayez:
function random(minimum, maximum) {
var bool = true;
while (bool) {
var number = (Math.floor(Math.random() * maximum + 1) + minimum);
if (number > 20) {
bool = true;
} else {
bool = false;
}
}
return number;
}
tilisez cette fonction pour obtenir des nombres aléatoires dans une plage donnée
function rnd(min,max){
return Math.floor(Math.random()*(max-min+1)+min );
}
Pour obtenir un nombre aléatoire dit entre 1 et 6, faites d'abord:
0.5 + (Math.random() * ((6 - 1) + 1))
Cela multiplie un nombre aléatoire par 6, puis ajoute 0,5. Tournez ensuite le nombre jusqu'à un entier positif en faisant:
Math.round(0.5 + (Math.random() * ((6 - 1) + 1))
Ceci arrondit le nombre au nombre entier le plus proche.
Ou pour le rendre plus compréhensible, procédez comme suit:
var value = 0.5 + (Math.random() * ((6 - 1) + 1))
var roll = Math.round(value);
return roll;
En général, le code pour faire cela en utilisant des variables est:
var value = (Min - 0.5) + (Math.random() * ((Max - Min) + 1))
var roll = Math.round(value);
return roll;
La raison pour laquelle on supprime 0,5 de la valeur minimale est que l'utilisation de la valeur minimale seule vous permettrait d'obtenir un entier supérieur de un à votre valeur maximale. En supprimant 0,5 de la valeur minimale, vous évitez essentiellement d’arrondir la valeur maximale.
J'espère que ça aide.
En utilisant le code suivant, vous pouvez générer un tableau de nombres aléatoires, sans répétition, dans une plage donnée.
function genRandomNumber(how_many_number,min,max) {
// parameters
// how_many_number : how many numbers you want to generate. For example it is 5.
// min(inclusive) : minimum/low value of a range. it must be any positive integer but less than max. i.e 4
// max(inclusive) : maximun value of a range. it must be any positive integer. i.e 50
// return type: array
var random_number = [];
for (var i = 0; i < how_many_number; i++) {
var gen_num = parseInt((Math.random() * (max-min+1)) + min);
do {
var is_exist = random_number.indexOf(gen_num);
if (is_exist >= 0) {
gen_num = parseInt((Math.random() * (max-min+1)) + min);
}
else {
random_number.Push(gen_num);
is_exist = -2;
}
}
while (is_exist > -1);
}
document.getElementById('box').innerHTML = random_number;
}
Je sais que cette question a déjà reçu une réponse, mais ma réponse pourrait aider quelqu'un.
J'ai trouvé cette méthode simple sur W3Schools:
Math.floor((Math.random() * max) + min);
J'espère que cela aiderait quelqu'un.
Nombre entier aléatoire entre le plus bas et le plus haut:
function randomRange(l,h){
var range = (h-l);
var random = Math.floor(Math.random()*range);
if (random === 0){random+=1;}
return l+random;
}
Pas la solution la plus élégante .. mais quelque chose de rapide.
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 code 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 Edge. Ainsi, si la fonction génère une valeur supérieure au maximum ou inférieure au minimum, vous.will.know.about.it.
<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>
Voici ce que j'utilise pour générer des nombres aléatoires.
function random(high,low) {
high++;
return Math.floor((Math.random())*(high-low))+low;
}
Nous exécutons bien high++
car Math.random()
génère un nombre aléatoire compris entre 0 (inclus) et 1(exclusive) Celui-ci étant exclu, il faut augmenter le haut de un avant d'exécuter aucun calcul. Nous soustrayons ensuite bas de haut, ce qui nous donne le nombre le plus élevé à générer - bas, puis + bas, ramenant le haut à la normale et rendant le nombre le plus bas au moins faible. alors nous retournons le nombre résultant
random(7,3)
pourrait retourner 3,4,5,6, or 7
Voici un exemple de fonction javascript qui peut générer un nombre aléatoire de toute longueur spécifiée sans utiliser Math.random ():
function genRandom(length)
{
const t1 = new Date().getMilliseconds();
var min = "1",max = "9";
var result;
var numLength = length;
if (numLength != 0)
{
for (var i = 1; i < numLength; i++)
{
min = min.toString() + "0";
max = max.toString() + "9";
}
}
else
{
min = 0;
max = 0;
return;
}
for (var i = min; i <= max; i++)
{
//Empty Loop
}
const t2 = new Date().getMilliseconds();
console.log(t2);
result = ((max - min)*t1)/t2;
console.log(result);
return result;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
/*
assuming that window.crypto.getRandomValues is available
the real range would be fron 0 to 1,998 instead of 0 to 2,000
See javascript documentation for explanation
https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
*/
var array = new Uint8Array(2);
window.crypto.getRandomValues(array);
console.log(array[0] + array[1]);
</script>
</body>
</html>
Uint8Array crée un tableau composé de 3 chiffres au maximum, soit un maximum de 999. Ce code est très court.
c’est ma position sur un nombre aléatoire dans une plage, car je voulais obtenir un nombre aléatoire dans une plage de base à exposant. par exemple. base = 10, exposant = 2, donne un nombre aléatoire de 0 à 100, idéalement, etc.
si cela aide à l'utiliser, le voici:
// get random number within provided base + exponent
// by Goran Biljetina --> 2012
function isEmpty(value){
return (typeof value === "undefined" || value === null);
}
var numSeq = new Array();
function add(num,seq){
var toAdd = new Object();
toAdd.num = num;
toAdd.seq = seq;
numSeq[numSeq.length] = toAdd;
}
function fillNumSeq (num,seq){
var n;
for(i=0;i<=seq;i++){
n = Math.pow(num,i);
add(n,i);
}
}
function getRandNum(base,exp){
if (isEmpty(base)){
console.log("Specify value for base parameter");
}
if (isEmpty(exp)){
console.log("Specify value for exponent parameter");
}
fillNumSeq(base,exp);
var emax;
var eseq;
var nseed;
var nspan;
emax = (numSeq.length);
eseq = Math.floor(Math.random()*emax)+1;
nseed = numSeq[eseq].num;
nspan = Math.floor((Math.random())*(Math.random()*nseed))+1;
return Math.floor(Math.random()*nspan)+1;
}
console.log(getRandNum(10,20),numSeq);
//testing:
//getRandNum(-10,20);
//console.log(getRandNum(-10,20),numSeq);
//console.log(numSeq);
Vous pouvez vous cet extrait de code,
let randomNumber = function(first,second){
let number = Math.floor(Math.random()*Math.floor(second));
while(number<first){
number = Math.floor(Math.random()*Math.floor(second));
}
return number;
}
Cela peut gérer la génération d'un nombre aléatoire UNIQUE jusqu'à 20 chiffres
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // precision --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.Push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
/ * Écrire une fonction appelée randUpTo
qui accepte un nombre et renvoie un nombre entier aléatoire compris entre 0 et ce nombre? * /
var randUpTo = function(num) {
return Math.floor(Math.random() * (num - 1) + 0);
};
/ * Ecrit une fonction appelée randBetween
qui accepte deux nombres représentant une plage et renvoie un nombre entier aléatoire entre ces deux nombres. * /
var randBetween = function (min, max) {
return Math.floor(Math.random() * (max - min - 1)) + min;
};
/ * Ecrit une fonction appelée randFromTill
qui accepte deux nombres représentant une plage et renvoie un nombre aléatoire compris entre min (inclus) et max (exclusif). * /
var randFromTill = function (min, max) {
return Math.random() * (max - min) + min;
};
/ * Ecrit une fonction appelée randFromTo
qui accepte deux nombres représentant une plage et renvoie un entier aléatoire compris entre min (inclus) et max (inclus) * /
var randFromTo = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Math.random()
est rapide et convient à de nombreuses fins, mais cela ne convient pas si vous avez besoin de valeurs cryptographiquement sécurisées (ce n'est pas sécurisé), ou si vous avez besoin d'entiers d'une distribution non uniforme totalement uniforme (la méthode de multiplication utilisée dans d'autres réponses produit certaines valeurs un peu plus souvent que d'autres).
Dans de tels cas, nous pouvons utiliser crypto.getRandomValues()
pour générer des entiers sécurisés et rejeter les valeurs générées que nous ne pouvons pas mapper de manière uniforme dans la plage cible. Ce sera plus lent, mais cela ne devrait pas être important, sauf si vous générez un très grand nombre de valeurs.
Pour clarifier le problème de la distribution biaisée, considérons le cas où nous voulons générer une valeur comprise entre 1 et 5, mais nous avons un générateur de nombres aléatoires qui produit des valeurs comprises entre 1 et 16 (une valeur de 4 bits). Nous voulons avoir le même nombre de valeurs générées mappées sur chaque valeur de sortie, mais 16 ne se divise pas également par 5: il reste un reste de 1. Nous devons donc rejeter 1 des valeurs générées possibles et continuer uniquement lorsque nous obtenons une des 15 valeurs inférieures qui peuvent être uniformément cartographiées dans notre plage cible. Notre comportement pourrait ressembler à ce pseudocode:
Generate a 4-bit integer in the range 1-16.
If we generated 1, 6, or 11 then output 1.
If we generated 2, 7, or 12 then output 2.
If we generated 3, 8, or 13 then output 3.
If we generated 4, 9, or 14 then output 4.
If we generated 5, 10, or 15 then output 5.
If we generated 16 then reject it and try again.
Le code suivant utilise une logique similaire, mais génère à la place un entier de 32 bits, car il s'agit de la plus grande taille d'entier commune pouvant être représentée par le type standard number
de JavaScript. (Cela pourrait être modifié pour utiliser BigInt
s si vous avez besoin d'une plage plus large.) Quelle que soit la plage choisie, la fraction des valeurs générées qui sont rejetées sera toujours inférieure à 0,5; le nombre attendu de rejets sera donc toujours moins de 1,0 et généralement proche de 0,0; vous n'avez pas besoin de vous soucier de la boucle pour toujours.
const randomInteger = (min, max) => {
const range = max - min;
const maxGeneratedValue = 0xFFFFFFFF;
const possibleResultValues = range + 1;
const possibleGeneratedValues = maxGeneratedValue + 1;
const remainder = possibleGeneratedValues % possibleResultValues;
const maxUnbiased = maxGeneratedValue - remainder;
if (!Number.isInteger(min) || !Number.isInteger(max) ||
max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) {
throw new Error('Arguments must be safe integers.');
} else if (range > maxGeneratedValue) {
throw new Error(`Range of ${range} (from ${min} to ${max}) > ${maxGeneratedValue}.`);
} else if (max < min) {
throw new Error(`max (${max}) must be >= min (${min}).`);
} else if (min === max) {
return min;
}
let generated;
do {
generated = crypto.getRandomValues(new Uint32Array(1))[0];
} while (generated > maxUnbiased);
return min + (generated % possibleResultValues);
};
console.log(randomInteger(-8, 8)); // -2
console.log(randomInteger(0, 0)); // 0
console.log(randomInteger(0, 0xFFFFFFFF)); // 944450079
console.log(randomInteger(-1, 0xFFFFFFFF));
// Error: Range of 4294967296 covering -1 to 4294967295 is > 4294967295.
console.log(new Array(12).fill().map(n => randomInteger(8, 12)));
// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]
J'ai créé cette fonction qui prend en compte des options telles que min, max, exclude (une liste d'ints à exclure) et seed (au cas où vous voudriez un générateur aléatoire initialisé).
get_random_int = function(args={})
{
let def_args =
{
min: 0,
max: 1,
exclude: false,
seed: Math.random
}
args = Object.assign(def_args, args)
let num = Math.floor(args.seed() * (args.max - args.min + 1) + args.min)
if(args.exclude)
{
let diff = args.max - args.min
let n = num
for(let i=0; i<diff*2; i++)
{
if(args.exclude.includes(n))
{
if(n + 1 <= args.max)
{
n += 1
}
else
{
n = args.min
}
}
else
{
num = n
break
}
}
}
return num
}
Il peut être utilisé comme:
let n = get_random_int
(
{
min: 0,
max: some_list.length - 1,
exclude: [3, 6, 5],
seed: my_seed_function
}
)
Ou plus simplement:
let n = get_random_int
(
{
min: 0,
max: some_list.length - 1
}
)
Ensuite, vous pouvez faire:
let item = some_list[n]
Gist: https://Gist.github.com/madprops/757deb000bdec25776d5036dae58ee6e