Генерация случайного числа между двумя числами в JavaScript

1799

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

Миргород
источник
12
Math.floor (Math.random () * 7)
Amjad Masad
65
Конечно .. Math.floor (Math.random () * 6 + 1)
Amjad Masad
3
Набиль Кадими также написал статью о том, как генерировать отрицательные случайные числа .
Madc
Вот полезная суть: gist.github.com/kerimdzhanov/7529623
Дан К.К.
почему такое решение Math.floor((Math.random()*10)+1);не может работать для вас, как указано здесь, на w3schools.com/jsref/jsref_random.asp ..?
Шашват

Ответы:

2118

Важный

Следующий код работает, только если минимальное значение равно 1. Это не работает для минимальных значений, кроме 1.

Если вы хотите получить случайное целое число от 1 ( и только 1 ) до 6, вы должны вычислить:

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

Куда:

  • 1 - начальный номер
  • 6 - количество возможных результатов (1 + начало (6) - конец (1) )
khr055
источник
45
Хотя @Mike это сработает, было бы лучше указать на более общую версию, так как у Francisc она ниже :-).
Рэймонд Мачира
59
-1. После поиска в Google я нашел этот вопрос, озаглавленный «Генерация случайного значения между двумя числами в Javascript». Не будет работать, если минимальное значение равно 0
Ydhem
18
Не работает, если вы хотите число между двумя большими числами, например. Math.floor (Math.random () * 900) + 700
Роб
15
Это работает, только если минимальное значение равно 1. Если минимальное значение равно 2, и мы все еще используем, это Math.floor(Math.random() * 6) + 2означает, что, если Math.random()результаты в 0,99, наше случайное значение будет7
антитоксическое
28
Этот код не хорошо, потому что, не работает с любым числом. Код @Francisc правильный.
Король Лев
2290
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

То, что он делает «дополнительно», это то, что он допускает случайные интервалы, которые не начинаются с 1. Таким образом, вы можете получить случайное число от 10 до 15, например. Гибкость.

Франциск
источник
5
это также замечательно, потому что, если кто-то не включает toаргумент arg, он 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)]. Т.е. вы можете получить результат, который находится за пределами диапазона, потому что он выше, чем макс.
Коллимарко
329

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;

** И всегда приятно напоминать (Мозилла):

Math.random () не предоставляет криптографически безопасных случайных чисел. Не используйте их для чего-либо, связанного с безопасностью. Вместо этого используйте API Web Crypto, а точнее метод window.crypto.getRandomValues ​​().

Лиор Элром
источник
Что-то, что меня смутило ... Math.floor (..) гарантирует, что число является целым числом, где Math.round (..) будет давать неравномерное распределение. Ссылка: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
alikuli
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.
pishpish
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
Вы не могли бы объяснить (или дать ссылки на) синтаксис ~~? Я не видел этого раньше! Элегантное решение, но трудно понять.
DiegoDD
27
Двойная тильда ~~a и побитовое ИЛИ (a | 0) - более быстрые способы написания Math.floor (a)
edi9999
7
a | 0это также самый быстрый и самый оптимизированный способ преобразования строки в целое число. Работает только со строками, содержащими целые числа ( "444"и "-444"), то есть без дробей / дробей. Это дает 0для всего, что терпит неудачу. Это одна из основных оптимизаций за asm.js.
Пилау
3
Примечание: если вы работаете с действительно большими числами, двойная тильда не сработает. Попробуйте ~~(Math.random() * (50000000000000 - 0 + 1)) + 0иMath.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM
3
«Двойная тильда и побитовое ИЛИ / - более быстрые способы написания Math dot floor» - красивый рифмующий куплет, который скрасил мое утро. Спасибо @ 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 <= max

Если мы вычтем мин из уравнения, это эквивалентно

0 <= (Х - мин) <= (Макс - мин)

Теперь давайте умножим это на случайное число r, которое

0 <= (X - мин) * r <= (макс - мин) * r

Теперь давайте вернем мин в уравнение

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

Теперь давайте выберем функцию, которая приводит к r так , что она удовлетворяет диапазону наших уравнений как [min, max]. Это возможно только если 0 <= r <= 1

ХОРОШО. Теперь диапазон r ie [0,1] очень похож на результат функции Math.random (). Не так ли?

Функция Math.random () возвращает псевдослучайное число с плавающей точкой в ​​диапазоне [0, 1); то есть от 0 (включительно) до, но не включая 1 (исключая)

Например,

Случай г = 0

min+ 0 * ( max- min) = мин

Случай г = 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;
ryebr3ad
источник
2
Верно. Я забыл ранд был 0 включительно. Починил это.
ryebr3ad
3
Это часть псевдокода ... кто-то может подумать, что это реально, и попытаться использовать его таким образом.
gravityboy
35
@gravityboy О чем ты говоришь? Если кто-то не может заменить номер на [выбрать номер ...], он может не подойти как программист.
ryebr3ad
7
@ ryebr3ad -1! сказано в javascript, а не в псевдокоде, и также не все читатели являются опытными программистами. Многие начинающие!
Стив
3
@ ryebr3ad: У меня был сотрудник, который преподавал стажерам среду базы данных, в которой они нуждались бы. Он сказал им выбрать все из таблицы, и они начали писать «выбрать все из ...» прямо в редакторе SQL-запросов. У него была такая же реакция, как и у вас.
Эллеседил
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даст вам цифры от мин до мин + макс, а это не то, что вы хотите. Первая ветвь ifявляется правильной, но ее можно было бы упростить, чтобы сказать return min + Math.random() * (max - min), что является правильным решением независимо от того, является ли 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

Фиксированная версия.

ElChupacabra
источник
Это не очень хорошее решение, так как оно не будет работать с нулевым значением min. Смотрите ответ @ Lior.
Себастьян
Конечно, это работает с нуля как минимальное значение. Ты пробовал? Нет причин, по которым это может не сработать. Он не будет работать с 0 как интервал, что не странно (интервал = 0? ...).
ЭльЧупакабра
Я несколько раз запускал эту функцию с нулевым значением min и никогда не получал ноль на выходе. Или мне не повезло ...
Себастьян
Вы правы. «+ интервал» был в неправильном месте. Проверьте это сейчас, пожалуйста. Странно то, что иногда console.log дает мне 0.300000004 вместо 0.3, например, 3 * 0.1, не было бы точно 0.3.
ЭльЧупакабра
9

пример

Вернуть случайное число от 1 до 10:

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

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

Попробуйте сами: здесь

-

или используя lodash / undescore:

_.random(min, max)

Документы: - lodash - undescore

Себастьян Лара
источник
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версии в ответе @ Francisc:

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
yonatanmn
источник
3

Крипто-сильное случайное целое число в диапазоне [a, b] (предположение: a <b)

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

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

Камил Келчевски
источник
1

Это должно работать:

const getRandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
sbr_amd
источник
1

Я обнаружил отличный новый способ сделать это, используя параметры по умолчанию ES6. Это очень изящно, поскольку допускает либо один аргумент, либо два аргумента. Вот:

function random(n, b = 0) {
    return Math.random() * (b-n) + n;
}
maburdi94
источник
1

Это примерно на девять лет позже, но randojs.com делает это простым однострочником:

rando(1, 6)

Вам просто нужно добавить это в заголовок вашего HTML-документа, и вы можете делать практически все, что вы хотите, со случайностью. Случайные значения из массивов, случайные элементы jquery, случайные свойства объектов и даже предотвращение повторений при необходимости.

<script src="https://randojs.com/1.0.0.js"></script>
Аарон Плочарчик
источник
Зачем добавлять зависимость, чтобы сделать что-то, что уже является одной строкой? Одержимость с добавлением библиотеки в сообществе JS является сумасшедшим
Даниэль Кук
легче читать и запоминать. Я согласен, хотя
Аарон Плохарчик
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));
gnrfan
источник
1

Попробуйте использовать:

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

AyushKatiyar
источник
1

вернуть 1-6, как кости в принципе,

return Math.round(Math.random() * 5 + 1);
Husky931
источник