Как сгенерировать случайное целое число в заданном диапазоне на JavaScript?
function getRandomNumber(min, max) {
return Math.floor(Math.random() * max) + min;
}
Но он работает неправильно: иногда выдаёт числа больше max, а иногда — меньше min. Например, при вызове getRandomNumber(5, 10) я получал 14 или 3. В чём моя ошибка? Как правильно написать функцию, которая будет возвращать случайное целое число в диапазоне [min, max] (включая обе границы)?
Буду благодарен за подробное объяснение с рабочими примерами. Заранее спасибо!
<<Правильный способ генерации случайного целого числа в диапазоне
Ваша ошибка в том, что вы умножаете Math.random() только на max, не учитывая разницу между max и min. Правильная формула выглядит так:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Давайте разберём, как это работает по шагам:
- Math.random() — возвращает число от 0 (включительно) до 1 (исключительно).
- (max - min + 1) — вычисляет количество целых чисел в диапазоне. Например, для [5, 10] это 10 - 5 + 1 = 6 чисел (5,6,7,8,9,10).
- Math.random() * (max - min + 1) — даёт число от 0 до 5.999... (не включая 6).
- Math.floor(...) — округляет вниз до целого, получаем 0,1,2,3,4 или 5.
- + min — сдвигает диапазон, получаем 5,6,7,8,9 или 10.
Вот несколько примеров использования:
// Случайное число от 1 до 10
console.log(getRandomInt(1, 10)); // может вывести 3, 7, 10 и т.д.
// Случайное число от -5 до 5
console.log(getRandomInt(-5, 5)); // может вывести -2, 0, 4 и т.д.
// Бросок кубика (1-6)
function rollDice() {
return getRandomInt(1, 6);
}
console.log(`Выпало: ${rollDice()}`);
Важное замечание: не путайте эту функцию с Math.round(). Если использовать Math.round() вместо Math.floor(), граничные значения (min и max) будут иметь вдвое меньшую вероятность выпадения, что нарушит равномерность распределения.
Для более продвинутых случаев (криптографическая стойкость) используйте crypto.getRandomValues():
function secureRandomInt(min, max) {
const range = max - min + 1;
const bytes = new Uint32Array(1);
crypto.getRandomValues(bytes);
return (bytes[0] % range) + min;
}
Эта функция подходит для генерации паролей или токенов, где важна непредсказуемость. Обычный Math.random() не является криптостойким.
<<Альтернативный подход с использованием Math.round()
Хотя основной метод с Math.floor() является стандартом, некоторые разработчики предпочитают использовать Math.round() для более интуитивного кода:
function getRandomIntRound(min, max) {
return Math.round(Math.random() * (max - min)) + min;
}
Однако у этого подхода есть существенный недостаток: граничные значения (min и max) выпадают с вероятностью в два раза меньшей, чем все остальные числа. Это происходит потому, что Math.round() округляет к ближайшему целому, и числа, попадающие в интервал [min - 0.5, min + 0.5), дают min, а для остальных чисел интервал шире.
Поэтому я рекомендую всегда использовать первый вариант с Math.floor(). Если вам нужно включить обе границы с равной вероятностью — это единственный правильный способ.
Для простых случаев (когда точное распределение не критично) можно использовать короткую запись:
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
console.log(rand(1, 100)); // случайное число от 1 до 100
Ответов пока нет.
Войдите чтобы оставить ответ