Створення випадкового числа між двома числами в JavaScript


1796

Чи є спосіб генерувати випадкове число у визначеному діапазоні (наприклад, від 1 до 6: 1, 2, 3, 4, 5 або 6) у JavaScript?


12
Math.floor (Math.random () * 7)
Амджад Масад

65
Впевнено .. Math.floor (Math.random () * 6 + 1)
Амджад Масад

3
Набіл Кадімі написав статтю про те, як генерувати також від’ємні випадкові числа .
madc

ось корисний гіст
Dan KK

чому таке рішення Math.floor((Math.random()*10)+1);не може працювати для вас, як зазначено тут на сайті w3schools.com/jsref/jsref_random.asp ..?
shashwat

Відповіді:


2115

Важливо

Наступний код працює лише за мінімального значення 1. Він не працює для мінімальних значень, крім 1.

Якщо ви хочете отримати випадкове ціле число між 1 ( і лише 1 ) і 6, ви обчислите:

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

Де:

  • 1 - початкове число
  • 6 - кількість можливих результатів (1 + початок (6) - кінець (1) )

45
Хоча це буде працювати, @Mike, найкраще було б вказати на більш універсальну версію, оскільки Франциск має її нижче :-).
Реймонд Мачіра

58
-1. Після Googling я знайшов це питання, заголовок - "Створення випадкового значення між двома числами в Javascript". " Не буде працювати, якщо значення мінімального значення дорівнює 0
Ydhem

18
Не працює, якщо потрібно число між двома більшими числами, наприклад. Math.floor (Math.random () * 900) + 700
Роб

14
Це працює лише в тому випадку, якщо мінімум дорівнює 1. Якщо мінус 2, а ми все ще використовуємо, Math.floor(Math.random() * 6) + 2значить, якщо Math.random()результат 0,99, наше випадкове значення буде7
антитоксичний

27
Цей код не гарний, оскільки не працює з будь-яким числом. Код @Francisc є правильним.
Король Левів

2283
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Що це робить "додатково" - це дозволяє випадкові інтервали, які не починаються з 1. Отже, ви можете отримати випадкове число, наприклад, від 10 до 15. Гнучкість.


5
це також чудово, тому що якщо хтось не включає toаргумент, fromаргумент подвоюється як максимум
Джейсон

12
Привіт. Це від 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/… )
Франциск

5
Прочитайте вищевказаний коментар. Випадково всередині [0,1), а не [0,1].
Франциск

3
Чудово працює, якщо нижня кількість дорівнює 0.
Робін Циммерманн

2
Зауважте, що це рішення є правильним лише у тому випадку, якщо min та max є цілими числами, інакше ви можете отримати результат у інтервалі [min, ceil (max)]. Тобто ви можете отримати результат, який знаходиться поза межами діапазону, оскільки вищий за макс.
collimarco

326

Math.random ()

Повертає ціле випадкове число між min ( включено ) та max ( включено ):

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

Або будь-яке випадкове число між min ( включено ) та max ( не включено ):

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

Корисні приклади (цілі числа):

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

** І завжди приємно нагадувати (Mozilla):

Math.random () не забезпечує криптографічно захищених випадкових чисел. Не використовуйте їх для нічого, що стосується безпеки. Замість цього скористайтеся API Web Crypto, а точніше методом window.crypto.getRandomValues ​​().


Щось мене бентежило ... Math.floor (..) гарантує, що число є цілим числом, де Math.round (..) дав би нерівномірний розподіл.
Відгук

1
Я довіряю цій відповіді. Хтось може дати посилання або чітке пояснення, чому це працює? Можливо, приклад того, як Math.round дав би упередження, і чому це означає, що ми повинні використовувати цю досить складну, здавалося б, формулу?
Робін Ендрюс

6
@alikuli Для діапазону [1,2], є 25% шанс Math.random()дасть вам ряд від одного з них [0,0.49], [0.5,0.99], [1,1.49], [1.5,1.99]. Округлення цих інтервалів призведе до 0, 1, 1, 2, що не є рівномірним розподілом. Настил їх призводить до 0, 0, 1, 1.
пішпіш

1
@shuji Це є , в Зокрема, правильна відповідь. Я просто хотів уточнити, чому використання Math.roundover Math.floorдасть різні результати.
пішпіш

Найбільш точне рішення, яке я знайшов: function getRandomInt(min, max) { return Math.round((min - 0.5) + Math.random() * (max - min + 1)); }
Садик

91

Інші рішення:

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

Спробуйте в Інтернеті


6
Ви не проти пояснити (або посилатися на) ~~ sintaxis? Я цього раніше не бачив! Елегантне рішення, але важко зрозуміти.
DiegoDD

27
Подвійний Тільд ~~a і Бітовий АБО (a | 0) - це більш швидкі способи написання Math.floor (a)
edi9999

7
a | 0це також найшвидший і оптимізований спосіб перетворення рядка в ціле число. Він працює лише з рядками, що містять цілі числа ( "444"і "-444"), тобто відсутні поплавці / дроби. Це дає результат 0для всього, що не вдається. Це одна з головних оптимізацій, що стоять за asm.js.
pilau

3
Примітка: якщо ви працюєте з деякими дійсно великими номерами, подвійний наліт не працюватиме. Спробуйте ~~(Math.random() * (50000000000000 - 0 + 1)) + 0іMath.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM

3
"Подвійний нахил і побіт АБО / - це швидші способи написання математичної підлоги" - це прекрасний рифмований пакет, який прояснив мій ранок. Дякую @ edi9999!
teedyay

60

TL; DR

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

Для отримання випадкового числа generateRandomInteger(-20, 20);

Пояснення нижче

Нам потрібно отримати випадкове ціле число, скажімо, X між min та max.

Правильно?

тобто min <= X <= макс

Якщо відняти від рівняння хв, це еквівалентно

0 <= (X - хв) <= (макс - хв)

Тепер давайте помножимо це на випадкове число r, яке є

0 <= (X - хв) * r <= (max - хв) * r

Тепер давайте додаємо хв до рівняння

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

Тепер виберемо функцію, в результаті якої r така, що вона відповідає нашому діапазону рівнянь як [min, max]. Це можливо лише в тому випадку, якщо 0 <= r <= 1

ДОБРЕ. Тепер діапазон r, тобто [0,1], дуже схожий на результат функції Math.random (). Чи не так?

Функція Math.random () повертає псевдовипадкове число з плаваючою комою в діапазоні [0, 1); тобто від 0 (включно) до 1, але не включаючи 1 (виключно)

Наприклад,

Випадок r = 0

min+ 0 * ( max- min) = хв

Випадок r = 1

min+ 1 * ( max- min) = макс

Випадковий випадок з використанням Math.random 0 <= r <1

min+ r * ( max- min) = X , де X має діапазон min <= X < max

Вищенаведений результат X є випадковим числовим числом. Однак завдяки Math.random () наша ліва межа включена, а права межа виключна. Для включення правої межі ми збільшуємо праву межу на 1 і поверх результату.

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

Для отримання випадкового числа

generateRandomInteger(-20, 20);



24
var x = 6; // can be any number
var rand = Math.floor(Math.random()*x) + 1;

2
Справді. Я забув, що ранд був 0 включно. Виправлено це.
ryebr3ad

3
Це частина псевдокоду ... хтось може подумати, що це справжнє, і спробувати його використовувати так.
gravityboy

35
@gravityboy Про що ти говориш? Якщо хтось не може замінити номер на [вибрати номер ...], він може бути непридатним як програміст.
ryebr3ad

7
@ ryebr3ad -1! сказано в JavaScript, а не в псевдо коді, а також не всі читачі є програмістами. Багато хто є початківцями!
Стів

3
@ ryebr3ad: У мене був колега, який навчав інтернів про середовище бази даних, їм потрібна підтримка. Він сказав їм вибрати все з таблиці, і вони почали писати "вибирати все з ..." прямо в редакторі запитів SQL. У нього була така ж реакція, як і у вас.
Ellesedil

22

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

Випадковий цілий число : щоб отримати випадкове ціле число між minі max, скористайтеся наступним кодом

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

Випадковий номер з плаваючою комою : щоб отримати випадкове число з плаваючою точкою між minі max, скористайтеся наступним кодом

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

Довідка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random


14

Математика не є моєю сильною стороною, але я працював над проектом, де мені потрібно було генерувати безліч випадкових чисел між позитивними та негативними.

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

Напр

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

Звичайно, ви можете також додати деяку перевірку, щоб переконатися, що ви цього не робите, крім чисел. Також переконайтесь, що min завжди менше або дорівнює max.


5
Це просто неправильно. min + Math.random() * maxдасть вам цифри між min та min + max, що не те, що ви хочете. Перша гілка ifє правильною, але її можна спростити return min + Math.random() * (max - min), що є правильним рішенням, незалежно від того, позитивний чи негативний мінус (див. Інші відповіді). Крім того, майте на увазі, що вам все одно потрібно підбити результат, якщо ви не хочете дробів.
Авіш

10

Я написав більш гнучку функцію, яка може дати вам випадкове число, але не тільки ціле число.

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

Виправлена ​​версія.


Це не гарне рішення, оскільки воно не працюватиме з нулем як мінімальне значення. Дивіться відповідь @ Ліора.
Себастьян

Звичайно, він працює з нулем як мінімальне значення. Ви пробували? Немає причини, чому це може не спрацювати. Він не буде працювати з 0 як інтервал, що не дивно (інтервал = 0? ...).
ElChupacabra

Я кілька разів запускав цю функцію з нулем як мінімальне значення і ніколи не отримував нуль у виході. Або мені не пощастило ...
Себастьян

Ти правий. "+ інтервал" опинився в неправильному місці. Перевірте це, будь ласка. Дивна річ, що іноді console.log дає мені 0,300000004 замість 0,3 як 3 * 0,1 не буде точно 0,3.
ElChupacabra

9

Приклад

Повернути випадкове число між 1 і 10:

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

Результатом може бути: 3

Спробуйте самі: тут

-

або використовуючи lodash / unescore:

_.random(min, max)

Документи: - лодаш - нестеро


1
значить, вам потрібно 9 чи 10 правильно? Якщо так: const randomNumber = Math.floor ((Math.random () * 10) + 1) const nineOrTen = randomNumber% 2 === 0? 9: 10
Себастьян Лара

7

Незважаючи на багато відповідей і майже такий самий результат. Я хотів би додати свою відповідь і пояснити її роботу. Тому що важливо зрозуміти його роботу, а не копіювати вставлення одного коду рядка. Генерація випадкових чисел - це не що інше, як проста математика.

КОД:

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));
}

6

Я шукав генератор випадкових чисел, написаний на TypeScript, і написав це, прочитавши всі відповіді, сподіваюся, що це буде працювати для кодерів TypeScript.

    Rand(min: number, max: number): number {
        return (Math.random() * (max - min + 1) | 0) + min;
    }   

5

Math.random() швидко і підходить для багатьох цілей, але це не доречно, якщо вам потрібні криптографічно захищені значення (це не захищено) або якщо вам потрібні цілі числа з цілком рівномірного неупередженого розподілу (підхід множення, який використовується в інших відповідях, дає певні значення трохи частіше ніж інші).

У таких випадках ми можемо використовувати crypto.getRandomValues()для створення захищених цілих чисел та відхиляти будь-які згенеровані значення, які ми не можемо рівномірно відобразити у цільовий діапазон. Це буде повільніше, але воно не повинно бути суттєвим, якщо ви не генеруєте надзвичайно велику кількість значень.

Для уточнення проблеми з упередженим розподілом розглянемо випадок, коли ми хочемо генерувати значення від 1 до 5, але у нас є генератор випадкових чисел, який виробляє значення між 1 і 16 (4-бітове значення). Ми хочемо, щоб однакове число згенерованих значень відображалося на кожне вихідне значення, але 16 не ділиться рівно на 5: воно залишає залишок 1. Отже, нам потрібно відхилити 1 можливих згенерованих значень і продовжувати лише тоді, коли отримаємо одне з 15 менших значень, яке можна рівномірно відобразити в нашому цільовому діапазоні. Наша поведінка може виглядати приблизно так:

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.

У наведеному нижче коді використовується аналогічна логіка, але натомість генерується 32-бітове ціле число, оскільки це найбільший загальний розмір цілих чисел, який може бути представлений стандартним numberтипом JavaScript . (Це може бути змінено для використання BigInts, якщо вам потрібен більший діапазон.) Незалежно від обраного діапазону, частка генерованих значень, які відхиляються, завжди буде менше 0,5, тому очікувана кількість відхилень завжди буде менше 1,0 і зазвичай близький до 0,0; вам не потрібно турбуватися про це петлі назавжди.

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]


Тепер це я називаю зайвим.
2xSamurai

2
@ 2xSamurai Там я оновив відповідь, щоб пояснити, чому вам може знадобитися це і як це працює. Це краще? : P
Джеремі Бенкс

Це зовсім не зайвий звіт, якщо ви хочете криптографічно захищені та рівномірно розподілені випадкові числа. Генерувати випадкові числа, які відповідають цим вимогам, важко. Чудова відповідь, @JeremyBanks.
Томаскоград

4

Додавання floatверсії з фіксованою точністю на основі intверсії у відповіді @ Франциска:

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

тому:

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

і для int відповіді

randomFloatFromInterval(1,3,0) // => 1, 2, 3


1

Це має працювати:

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

1

Я відкрив чудовий новий спосіб зробити це за допомогою параметрів за замовчуванням ES6. Це дуже вишукано, оскільки дозволяє або один аргумент, або два аргументи. Ось:

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

1

На це дев'ять років пізніше, але randojs.com робить це простим однолінійним :

rando(1, 6)

Вам просто потрібно додати це до голови вашого html-документа, і ви можете легко робити все, що завгодно, з випадковістю. Випадкові значення масивів, випадкових елементів jquery, випадкових властивостей об'єктів і навіть запобігання повторень у разі потреби.

<script src="https://randojs.com/1.0.0.js"></script>

Навіщо додавати залежність, щоб зробити щось, що вже є однорівневим? Одержимість додаванням бібліотек у спільноті JS шалена
Daniel Cooke

легше читати і запам’ятовувати. Я згоден, хоча
Аарон Плочарчик

1

Це працює для мене і створює такі значення, як стандартна бібліотечна функція Python: random.randint :


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

console.log("Random integer: " + randint(-5, 5));


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.