2501 votes

Générer des nombres entiers aléatoires en JavaScript dans une plage spécifique ?

Comment puis-je générer des nombres entiers aléatoires entre deux variables spécifiées en JavaScript, par ex. x = 4 y y = 8 produirait l'un des éléments suivants 4, 5, 6, 7, 8 ?

2 votes

Voici un résumé utile : gist.github.com/kerimdzhanov/7529623

15 votes

Remarque : pour ceux qui utilisent npm et recherchent une solution rapide, fiable et prête à l'emploi, il y a lodash.random qui peut être facilement exigé avec un encombrement très faible (il importera juste la méthode elle-même et non le lodash entier).

0 votes

Si elle doit être crypto sécurisée developer.mozilla.org/fr/US/docs/Web/API/RandomSource/

4793voto

Ionuț G. Stan Points 62482

Il existe quelques exemples sur le site Réseau de développeurs Mozilla page :

/**
 * 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 Number entre 0 (inclusif) et 1 (exclusif). Nous avons donc un intervalle comme celui-ci :

[0 .................................... 1)

Maintenant, nous aimerions un nombre 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, d'abord, nous devons factoriser un peu le problème en soustrayant min du second 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 au hasard :

                Math.random()
                    |
[0 .................................... 1)
[0 .................................... max - min)
                    |
                    x (what we need)

Donc, afin de trouver x nous le ferions :

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 y max les deux inclus.

Maintenant, pour obtenir des entiers, vous pouvez utiliser round , ceil o floor .

Vous pourriez utiliser Math.round(Math.random() * (max - min)) + min ce qui donne cependant une distribution non uniforme. Les deux, min y max n'ont qu'environ la moitié des chances de rouler :

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 é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() y -1 dans cette équation car max a maintenant un peu moins de chance d'être lancé, mais vous pouvez lancer le (indésirable) min-1 résultat aussi.

1 votes

Pouvez-vous expliquer pourquoi vous devez en ajouter un au max-min ? Je ne comprends pas cette partie.

18 votes

Il fait ça seulement parce qu'il appelle floor qui s'arrondit à la baisse.

6 votes

@thezachperson31 Vous pourriez utiliser round mais aussi les deux, min y max n'avait que la moitié des chances de rouler comme les autres numéros. Vous pouvez aussi soustraire un et prendre ceil . Cela laisse toutefois le max avec un minimum de chance en moins de rouler en raison de la [0,1) Intervalle.

643voto

Darin Dimitrov Points 528142
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;

33 votes

Je sais que c'est une TRES vieille réponse, mais en utilisant (Math.random() * (maximum - minimum + 1) ) << 0 est plus rapide.

23 votes

@IsmaelMiguel Utilisation des opérateurs binaires ( x << 0 , x | 0 , ~~x ) au lieu de Math.floor() convertit x en un complément à deux avec une portée beaucoup plus petite que celle de Number.MAX_SAFE_INTEGER (2³²¹ contre 2³), il faut donc l'utiliser avec prudence !

0 votes

@IsmaelMiguel Yo je viens d'essayer votre méthode dans la console et j'ai obtenu par hasard une valeur négative ! Math.randRange = (minimum, maximum) => (Math.random() * (maximum - minimum + 1) ) << 0 Math.randRange(2,657348096152) -1407373159

64voto

Gordon Gustafson Points 14778
function getRandomizer(bottom, top) {
    return function() {
        return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
    }
}

l'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, renvoie un entier aléatoire entre les valeurs suivantes bottom y top inclusive. Nous disons "inclusif" parce que nous voulons inclure à la fois le bas et le haut dans la gamme des nombres qui peuvent être retournés. De cette façon, getRandomizer( 1, 6 ) retournera soit 1, 2, 3, 4, 5, ou 6.

(le bas est le numéro le plus bas, le haut est le numéro le plus élevé)

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 y bottom nous aurons un double quelque part entre 0 y 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 nombres entiers compris entre 0 y top-bottom . Le 1 peut prêter à confusion, mais il doit être présent car nous arrondissons toujours à l'unité inférieure, de sorte que le nombre supérieur ne sera jamais atteint sans lui. La décimale aléatoire que nous générons doit se situer dans la plage suivante 0 a (1+top-bottom) afin d'arrondir à l'inférieur et d'obtenir un int dans l'intervalle 0 a top-bottom

Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom

Le code de l'exemple précédent nous a donné un nombre entier dans la plage 0 y top-bottom Il ne nous reste donc plus qu'à ajouter bottom à ce résultat pour obtenir un entier dans l'intervalle bottom y top inclusive. :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 approfondir le code de vérification des arguments car il est assez loin de l'intention de la question originale.

1 votes

Je réalise que c'est environ 2½ ans plus tard, mais avec l'entrée 1 et 6, votre fonction renvoie les valeurs 1,2,3,4 et 5, mais jamais un 6, comme elle le ferait si elle était "inclusive".

10 votes

@some, ça pourrait être pire, je suis 2½ ans + 1 jour plus tard ^^.

0 votes

+1, j'ai testé votre code, il semble créer une valeur correcte. Structure créative pour gérer des scénarios fixes qui pourraient se répéter beaucoup dans le code.

43voto

Prasobh.K Points 148

Renvoie un nombre aléatoire entre 1 et 10 :

Math.floor((Math.random()*10) + 1); 

Renvoie un nombre aléatoire entre 1 et 100 :

Math.floor((Math.random()*100) + 1)

0 votes

Votre "entre" est-il inclusif ou exclusif ? c'est-à-dire est-il [1,10], [1,10], (1,10], ou (1,10) ?

1 votes

Il est partiellement inclusif : [1, *)

0 votes

Quelle est l'utilité de + 1 à la fin de la fonction ? Elle fonctionne parfaitement je suppose.

39voto

Codler Points 4395
function randomRange(min, max) {
  return ~~(Math.random() * (max - min + 1)) + min
}

Alternative si vous utilisez Underscore.js vous pouvez utiliser

_.random(min, max)

2 votes

Underscore fournit en fait un _.uniqueId() que vous pouvez appeler pour les modèles côté client.

0 votes

En utilisant des opérateurs binaires ( x << 0 , x | 0 , ~~x ) au lieu de Math.floor() convertit x en un complément à deux avec une portée beaucoup plus petite que celle de Number.MAX_SAFE_INTEGER (2³²¹ contre 2³), il faut donc l'utiliser avec prudence !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X