Générer un nombre aléatoire entre deux nombres en JavaScript

1798

Existe-t-il un moyen de générer un nombre aléatoire dans une plage spécifiée (par exemple de 1 à 6: 1, 2, 3, 4, 5 ou 6) en JavaScript?

Mirgorod
la source
12
Math.floor (Math.random () * 7)
Amjad Masad
65
Bien sûr. Math.floor (Math.random () * 6 + 1)
Amjad Masad
3
Nabil Kadimi a également écrit un article sur la façon de générer des nombres aléatoires négatifs .
madc
voici un aperçu
Dan KK
pourquoi une solution comme celle- Math.floor((Math.random()*10)+1);ci ne peut pas fonctionner pour vous comme spécifié ici sur w3schools.com/jsref/jsref_random.asp ..?
shashwat

Réponses:

2118

Important

Le code suivant ne fonctionne que si la valeur minimale est 1. Il ne fonctionne pas pour des valeurs minimales autres que1 .

Si vous vouliez obtenir un entier aléatoire entre 1 ( et seulement 1 ) et 6, vous calculeriez:

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

Où:

  • 1 est le numéro de départ
  • 6 est le nombre de résultats possibles (1 + début (6) - fin (1) )
khr055
la source
45
Alors que cela fonctionnerait, @Mike, il serait préférable de souligner la version plus générique car Francisc l'a ci-dessous :-).
Raymond Machira
59
-1. Après la recherche sur Google, j'ai trouvé cette question, le titre est "" Générer une valeur aléatoire entre deux nombres en Javascript "." Ne fonctionnera pas si la valeur
minimale
18
Ne fonctionne pas si vous voulez un nombre entre deux grands nombres, par exemple. Math.floor (Math.random () * 900) + 700
Rob
15
Cela ne fonctionne que si le minimum est 1. Si le min est 2 et que nous utilisons encore Math.floor(Math.random() * 6) + 2signifie que si les Math.random()résultats en 0.99 notre valeur aléatoire serait7
antitoxique
28
Ce code n'est pas bon car, ne fonctionne avec aucun numéro. Le code @Francisc est correct.
Roi Lion
2289
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Ce qu'il fait "extra", c'est qu'il permet des intervalles aléatoires qui ne commencent pas par 1. Vous pouvez donc obtenir un nombre aléatoire de 10 à 15 par exemple. Souplesse.

Francisc
la source
5
c'est aussi très bien parce que si quelqu'un n'inclut pas l' toargument, l' fromarg double le maximum
Jason
12
Bonjour. Cela vient de MDN: Returns a floating-point, pseudo-random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive), which you can then scale to your desired range.( developer.mozilla.org/en-US/docs/JavaScript/Reference/… )
Francisc
5
Lisez le commentaire ci-dessus. Aléatoire est à l'intérieur de [0,1), pas de [0,1].
Francisc
3
Fonctionne très bien si le nombre inférieur est 0.
Robin Zimmermann
2
Notez que cette solution n'est correcte que si min et max sont des entiers, sinon vous pouvez obtenir un résultat dans l'intervalle [min, ceil (max)]. C'est-à-dire que vous pouvez obtenir un résultat qui est hors de portée car supérieur à max.
collimarco
329

Math.random ()

Renvoie un nombre aléatoire entier compris entre min ( inclus ) et max ( inclus ):

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

Ou tout nombre aléatoire compris entre min ( inclus ) et max ( non inclus ):

function randomNumber(min, max) {
  return Math.random() * (max - min) + min;
}

Exemples utiles (entiers):

// 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;

** Et toujours agréable d'être rappelé (Mozilla):

Math.random () ne fournit pas de nombres aléatoires sécurisés cryptographiquement. Ne les utilisez pas pour tout ce qui concerne la sécurité. Utilisez plutôt l'API Web Crypto, et plus précisément la méthode window.crypto.getRandomValues ​​().

Lior Elrom
la source
Quelque chose qui m'a dérouté ... le Math.floor (..) garantit que le nombre est un entier où Math.round (..) donnerait une distribution inégale. Réf: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
alikuli
1
J'ai confiance en cette réponse. Quelqu'un peut-il donner un lien ou une explication claire de pourquoi cela fonctionne? Peut-être un exemple de la façon dont Math.round donnerait un biais, et pourquoi cela signifie-t-il que nous devons utiliser cette formule d'aspect plutôt complexe?
Robin Andrews,
6
@alikuli Pour une gamme de [1,2], il y a 25% de chance Math.random()vous donnerait un certain nombre d'un de ces [0,0.49], [0.5,0.99], [1,1.49], [1.5,1.99]. Arrondir ces intervalles donnerait 0, 1, 1, 2, ce qui n'est pas une distribution uniforme. Plancher les résultats en 0, 0, 1, 1.
pishpish
1
Ce @shuji est , entre autres, la bonne réponse. Je voulais juste clarifier pourquoi l'utilisation de Math.roundover Math.floordonnerait des résultats différents.
pishpish
La solution la plus précise que j'ai trouvée: function getRandomInt(min, max) { return Math.round((min - 0.5) + Math.random() * (max - min + 1)); }
Sadik
91

Autres solutions:

  • (Math.random() * 6 | 0) + 1
  • ~~(Math.random() * 6) + 1

Essayez en ligne

Vishal
la source
6
Pourriez-vous expliquer (ou donner des références à) la ~~ sintaxis? Je ne l'ai jamais vu auparavant! Solution élégante mais difficile à comprendre.
DiegoDD
27
Double Tilde ~~a et OR au niveau du bit (a | 0) sont des moyens plus rapides d'écrire Math.floor (a)
edi9999
7
a | 0est également le moyen le plus rapide et le plus optimisé pour convertir une chaîne en entier. Il ne fonctionne qu'avec des chaînes contenant des entiers ( "444"et "-444"), c'est-à-dire sans flottants / fractions. Il donne un 0pour tout ce qui échoue. C'est l'une des principales optimisations derrière asm.js.
pilau
3
Remarque: si vous travaillez avec de très grands nombres, le double tilde ne fonctionnera pas. Essayez ~~(Math.random() * (50000000000000 - 0 + 1)) + 0etMath.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM
3
"Double tilde et OR au niveau du bit / sont des moyens plus rapides d'écrire Math dot floor" est un magnifique distique de rimes qui a égayé ma matinée. Merci @ edi9999!
teedyay
60

TL; DR

function generateRandomInteger(min, max) {
  return Math.floor(min + Math.random()*(max + 1 - min))
}

Pour obtenir le nombre aléatoire generateRandomInteger(-20, 20);

EXPLICATION CI-DESSOUS

Nous devons obtenir un entier aléatoire, disons X entre min et max.

Droite?

c'est-à-dire min <= X <= max

Si nous soustrayons min de l'équation, cela équivaut à

0 <= (X - min) <= (max - min)

Maintenant, multiplions cela par un nombre aléatoire r qui est

0 <= (X - min) * r <= (max - min) * r

Maintenant, ajoutons de nouveau min à l'équation

min <= min + (X - min) * r <= min + (max - min) * r

Maintenant, permet de choisir une fonction qui résulte en r telle qu'elle satisfait notre plage d'équations comme [min, max]. Ceci n'est possible que si 0 <= r <= 1

D'ACCORD. Maintenant, la plage de r ie [0,1] est très similaire au résultat de la fonction Math.random (). N'est-ce pas?

La fonction Math.random () renvoie un nombre pseudo-aléatoire à virgule flottante dans la plage [0, 1); c'est-à-dire de 0 (inclus) à 1 non compris (exclusif)

Par exemple,

Cas r = 0

min+ 0 * ( max- min) = min

Cas r = 1

min+ 1 * ( max- min) = max

Cas aléatoire utilisant Math.random 0 <= r <1

min+ r * ( max- min) = X , où X a une plage de min <= X < max

Le résultat ci-dessus X est un numérique aléatoire. Cependant, en raison de Math.random (), notre limite gauche est inclusive et la limite droite est exclusive. Pour inclure notre limite droite, nous augmentons la limite droite de 1 et fixons le résultat.

function generateRandomInteger(min, max) {
  return Math.floor(min + Math.random()*(max + 1 - min))
}

Pour obtenir le nombre aléatoire

generateRandomInteger(-20, 20);

Faiz Mohamed Haneef
la source
25

Ou, dans Underscore

_.random(min, max)
vladiim
la source
24
var x = 6; // can be any number
var rand = Math.floor(Math.random()*x) + 1;
ryebr3ad
la source
2
En effet. J'ai oublié que rand était 0 inclus. A corrigé.
ryebr3ad
3
Cela fait partie du pseudocode ... quelqu'un pourrait penser que c'est réel et essayer de l'utiliser comme ça.
gravityboy
35
@gravityboy De quoi parlez-vous? Si quelqu'un ne peut pas substituer un nombre à [choisir un numéro ...], il pourrait ne pas convenir en tant que programmeur.
ryebr3ad
7
@ ryebr3ad -1! il est dit en javascript pas en pseudo-code et tous les lecteurs ne sont pas des programmeurs accomplis. Beaucoup sont débutants!
Steve
3
@ ryebr3ad: J'ai eu un collègue qui enseignait aux stagiaires un environnement de base de données dont ils auraient besoin de soutien. Il leur a dit de tout sélectionner dans une table et ils ont commencé à écrire "tout sélectionner dans ..." directement dans l'éditeur de requête SQL. Il a eu la même réaction que toi.
Ellesedil
22

jsfiddle: https://jsfiddle.net/cyGwf/477/

Entier aléatoire : pour obtenir un entier aléatoire entre minet max, utilisez le code suivant

function getRandomInteger(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

Numéro à virgule flottante aléatoire: pour obtenir un nombre à virgule flottante aléatoire entre minet max, utilisez le code suivant

function getRandomFloat(min, max) {
  return Math.random() * (max - min) + min;
}

Référence: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random

Razan Paul
la source
14

Les mathématiques ne sont pas mon point fort, mais j'ai travaillé sur un projet où je devais générer beaucoup de nombres aléatoires entre les deux positifs et négatifs.

function randomBetween(min, max) {
    if (min < 0) {
        return min + Math.random() * (Math.abs(min)+max);
    }else {
        return min + Math.random() * max;
    }
}

Par exemple

randomBetween(-10,15)//or..
randomBetween(10,20)//or...
randomBetween(-200,-100)

Bien sûr, vous pouvez également ajouter une validation pour vous assurer de ne pas le faire avec autre chose que des chiffres. Assurez-vous également que min est toujours inférieur ou égal à max.

Petter Thowsen
la source
5
C'est tout simplement faux. min + Math.random() * maxvous donnera des nombres entre min et min + max, ce qui n'est pas ce que vous voulez. La première branche de la ifest correcte, mais pourrait être simplifiée pour dire return min + Math.random() * (max - min), quelle est la bonne solution, que min soit positif ou négatif (voir les autres réponses). Gardez également à l'esprit que vous devez toujours déterminer le résultat si vous ne voulez pas de fractions.
Avish
10

J'ai écrit une fonction plus flexible qui peut vous donner un nombre aléatoire mais pas seulement un entier.

function rand(min,max,interval)
{
    if (typeof(interval)==='undefined') interval = 1;
    var r = Math.floor(Math.random()*(max-min+interval)/interval);
    return r*interval+min;
}

var a = rand(0,10); //can be 0, 1, 2 (...) 9, 10
var b = rand(4,6,0.1); //can be 4.0, 4.1, 4.2 (...) 5.9, 6.0

Version fixe.

ElChupacabra
la source
Ce n'est pas une bonne solution car cela ne fonctionnera pas avec zéro comme valeur min. Voir la réponse de @ Lior.
Sebastien
Bien sûr, cela fonctionne avec zéro comme valeur min. As-tu essayé? Il n'y a aucune raison pour que cela ne fonctionne pas. Cela ne fonctionnera pas avec 0 comme intervalle ce qui n'est pas étrange (intervalle = 0? ...).
ElChupacabra
J'ai exécuté plusieurs fois cette fonction avec zéro comme valeur min et je n'ai jamais obtenu zéro dans la sortie. Ou je n'ai pas la chance ...
Sébastien
Tu as raison. "+ interval" était au mauvais endroit. Testez-le maintenant s'il vous plaît. Chose étrange que parfois console.log me donne 0.300000004 au lieu de 0.3 comme 3 * 0.1 ne serait pas exactement 0.3.
ElChupacabra
9

Exemple

Renvoyez un nombre aléatoire entre 1 et 10:

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

Le résultat pourrait être: 3

Essayez-vous: ici

-

ou en utilisant lodash / undescore:

_.random(min, max)

Documents: - lodash - undescore

Sebastián Lara
la source
1
vous avez donc besoin de 9 ou 10 à droite? Si oui: const randomNumber = Math.floor ((Math.random () * 10) + 1) const nineOrTen = randomNumber% 2 === 0? 9: 10
Sebastián Lara
7

Malgré de nombreuses réponses et presque le même résultat. Je voudrais ajouter ma réponse et expliquer son fonctionnement. Parce qu'il est important de comprendre son fonctionnement plutôt que de copier-coller un code de ligne. Générer des nombres aléatoires n'est rien d'autre que de simples calculs.

CODE:

function getR(lower, upper) {

  var percent = (Math.random() * 100);
  // this will return number between 0-99 because Math.random returns decimal number from 0-0.9929292 something like that
  //now you have a percentage, use it find out the number between your INTERVAL :upper-lower 
  var num = ((percent * (upper - lower) / 100));
  //num will now have a number that falls in your INTERVAL simple maths
  num += lower;
  //add lower to make it fall in your INTERVAL
  //but num is still in decimal
  //use Math.floor>downward to its nearest integer you won't get upper value ever
  //use Math.ceil>upward to its nearest integer upper value is possible
  //Math.round>to its nearest integer 2.4>2 2.5>3   both lower and upper value possible
  console.log(Math.floor(num), Math.ceil(num), Math.round(num));
}
Arun Sharma
la source
6

Je cherchais un générateur de nombres aléatoires écrit en TypeScript et je l'ai écrit après avoir lu toutes les réponses, j'espère que cela fonctionnera pour les codeurs TypeScript.

    Rand(min: number, max: number): number {
        return (Math.random() * (max - min + 1) | 0) + min;
    }   
Erdi İzgi
la source
5

Math.random() est rapide et convient à de nombreuses fins, mais ce n'est pas approprié si vous avez besoin de valeurs sécurisées sur le plan cryptographique (ce n'est pas sécurisé), ou si vous avez besoin d'entiers d'une distribution sans biais complètement uniforme (l'approche 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 toutes les valeurs générées que nous ne pouvons pas mapper uniformément dans la plage cible. Ce sera plus lent, mais il ne devrait être significatif que si vous générez un nombre extrêmement élevé de valeurs.

Pour clarifier le problème de distribution biaisée, considérons le cas où nous voulons générer une valeur entre 1 et 5, mais nous avons un générateur de nombres aléatoires qui produit des valeurs entre 1 et 16 (une valeur de 4 bits). Nous voulons avoir le même nombre de valeurs générées correspondant à 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 l'une des 15 valeurs inférieures qui peuvent être uniformément mappé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 32 bits, car il s'agit de la plus grande taille d'entier commun pouvant être représentée par le numbertype standard de JavaScript . (Cela peut être modifié pour utiliser BigInts si vous avez besoin d'une plus grande plage.) Quelle que soit la plage choisie, la fraction des valeurs générées qui sont rejetées sera toujours inférieure à 0,5, donc le nombre attendu de rejets sera toujours inférieur à 1,0 et généralement proche de 0,0; vous n'avez pas à vous en préoccuper en 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]

Jeremy Banks
la source
Maintenant, c'est ce que j'appelle exagéré.
2xSamurai
2
@ 2xSamurai Là, j'ai mis à jour la réponse pour expliquer pourquoi vous pourriez en avoir besoin et comment cela fonctionne. Est-ce mieux? : P
Jeremy Banks
Ce n'est pas exagéré du tout si vous voulez des nombres aléatoires cryptographiquement sécurisés et uniformément distribués. Il est difficile de générer des nombres aléatoires qui répondent à ces exigences. Excellente réponse, @JeremyBanks.
thomaskonrad
4

Ajout floatavec une version de précision fixe basée sur la intversion dans la réponse de @ Francisc:

function randomFloatFromInterval (min, max, fractionDigits) {
  const fractionMultiplier = Math.pow(10, fractionDigits)
  return Math.round(
    (Math.random() * (max - min) + min) * fractionMultiplier,
  ) / fractionMultiplier
}

donc:

randomFloatFromInterval(1,3,4) // => 2.2679, 1.509, 1.8863, 2.9741, ...

et pour réponse int

randomFloatFromInterval(1,3,0) // => 1, 2, 3
yonatanmn
la source
3

Nombre entier aléatoire crypto-fort dans la plage [a, b] (hypothèse: a <b)

let rand= (a,b)=> a+(b-a+1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32|0

console.log( rand(1,6) );

Kamil Kiełczewski
la source
1

Cela devrait fonctionner:

const getRandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
sbr_amd
la source
1

J'ai découvert une excellente nouvelle façon de le faire en utilisant les paramètres par défaut d'ES6. Il est très astucieux car il autorise soit un argument, soit deux arguments. C'est ici:

function random(n, b = 0) {
    return Math.random() * (b-n) + n;
}
maburdi94
la source
1

C'est environ neuf ans de retard, mais randojs.com en fait un simple doublure:

rando(1, 6)

Vous avez juste besoin d'ajouter cela en tête de votre document html, et vous pouvez faire à peu près tout ce que vous voulez avec aléatoire. Valeurs aléatoires des tableaux, éléments jquery aléatoires, propriétés aléatoires des objets, et même empêchant les répétitions si nécessaire.

<script src="https://randojs.com/1.0.0.js"></script>
Aaron Plocharczyk
la source
Pourquoi ajouter une dépendance pour faire quelque chose qui est déjà monoligne? L'obsession de l'ajout de bibliothèques dans la communauté JS est folle
Daniel Cooke
plus facile à lire et à mémoriser. je suis d'accord cependant
Aaron Plocharczyk
1

Cela fonctionne pour moi et produit des valeurs comme la fonction de bibliothèque standard random.randint de Python :


function randint(min, max) {
   return Math.round((Math.random() * Math.abs(max - min)) + min);
}

console.log("Random integer: " + randint(-5, 5));
gnrfan
la source
1

Essayez d'utiliser:

function random(min, max) {
   return Math.round((Math.random() *( Math.abs(max - min))) + min);
}
console.log(random(1, 6));

AyushKatiyar
la source
1

renvoyer 1-6 comme un dé en gros,

return Math.round(Math.random() * 5 + 1);
Husky931
la source