Пока вы думаете, что получаете по‑настоящему случайное число, JavaScript запускает определённый алгоритм: применяет математическую формулу и генерирует значение, которое лишь выглядит как случайность.
В этой статье разберём, как работает Math.random(), почему он всегда возвращает числа меньше 1 и как быть, если требуется криптографически стойкий рандом.
Что такое Math.random() в JavaScript?
Math.random() — это встроенный метод JavaScript, который возвращает псевдослучайное число с плавающей точкой от 0 (включительно) до 1 (не включительно).
Как работает метод Math.random()
Math.random() работает на основе псевдослучайного генератора (PRNG — Pseudo-Random Number Generator). Это значит, что вся «случайность» — результат математической формулы. Алгоритм запускается от некоторого начального значения — сида (seed) — и даёт последовательность чисел, которые выглядят случайными, но при желании её можно воспроизвести.
Диапазон возвращаемых значений (от 0 до 1)
Каждый вызов Math.random() возвращает число в диапазоне 0 ≤ x < 1. То есть 0 может попасться (редко, но может), а вот 1 вообще никогда.
Например:
console.log(Math.random());

Почему меньше одного? Потому что так устроена внутренняя логика распределения чисел. Это удобно для масштабирования — умножаем на нужный диапазон и получаем значения от 0 до N, исключая крайний случай.
Полезный блок со скидкой
Если вам интересно разбираться со смартфонами, компьютерами и прочими гаджетами и вы хотите научиться создавать софт под них с нуля или тестировать то, что сделали другие, — держите промокод Практикума на любой платный курс: KOD (можно просто на него нажать). Он даст скидку при покупке и позволит сэкономить на обучении.
Бесплатные курсы в Практикуме тоже есть — по всем специальностям и направлениям, начать можно в любой момент, карту привязывать не нужно, если что.
Базовое использование Math.random()
Простой пример генерации случайного числа
Начнём с самого простого, с синтаксиса метода Math.random():
Math.random()
Он вызывается без аргументов, и в результате мы получаем число с плавающей точкой от 0 (включительно) до 1 (не включительно). На каждый вызов — новое число.
Если нужно просто посмотреть результат — можно сразу вызвать метод в console.log(). Но чаще всего это значение требуется использовать дальше: передать в функцию, умножить на диапазон, округлить, сравнить, сохранить для расчётов и т. д. В таких случаях его лучше положить в переменную:
// Генерируем число и сохраняем в переменную
let randomNumber = Math.random();
// Теперь можем работать с этим числом дальше
console.log(randomNumber);

Теперь randomNumber — это наше случайное значение, с которым можно строить дальнейшую логику. Например:
- умножить на 10, чтобы получить число от 0 до 10;
- преобразовать в целое с
Math.floor(); - проверить, больше ли оно 0,5, и принять решение;
- использовать как индекс для случайного выбора из массива.
Более интересные примеры рассмотрим в следующих разделах.
Почему числа всегда меньше 1
Каждое значение, которое возвращает Math.random(), всегда меньше 1, потому что по стандарту ECMAScript верхняя граница не включается. Да, можно получить 0,000000000000001, но не 1,0000000000. Даже если миллион раз вызвать — не выйдет.
Это сделано специально, чтобы исключить граничный случай, где результат умножения, например, Math.random() * 10 мог бы случайно превратиться в 10 и сломать вам всю логику округления с Math.floor().
Представьте, вы делаете выбор из 10 элементов в массиве по индексу:
let index = Math.floor(Math.random() * 10);
Здесь мы умножаем случайное число от 0 до <1 на 10, а потом округляем его вниз. Это даёт значения от 0 до 9 — подходит для массива из 10 элементов (array[0] до array[9]).
Но если бы Math.random() возвращал ровно 1, то было бы так:
Math.floor(1 * 10) === 10
Здесь array[10] уже за пределами массива. Ошибка, грусть, undefined. Поэтому верхняя граница и отрезается.
Как получить случайное число в заданном диапазоне
Math.random() сам по себе — это просто число от 0 до 1. Но в реальной жизни нам обычно нужно что-то более осмысленное: случайный номер заказа, рандомный индекс массива, дробное значение в заданных границах и т. п. Разберёмся, как превратить Math.random() в полезный инструмент.
Формула для целых чисел
Для получения случайного целого числа от min до max включительно используют такую формулу:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Вот что здесь происходит:
Math.random()генерирует число от 0 до 0,999…* (max – min + 1)растягивает диапазон, чтобы попасть в нужную длину (например, от 1 до 10 = 10 чисел, а не 9);Math.floor()округляет вниз, чтобы получить целое;+ minсдвигает всё так, чтобы диапазон начинался не с нуля, а с нужного минимума.
Почему в формуле +1 ? Потому что Math.random() никогда не возвращает 1, а Math.floor() всегда округляет вниз. Без +1 вы бы никогда не получили max, только max – 1.
getRandomInt(1, 10); // может вернуть 1, 2, 3 … 10

getRandomInt(0, 99); // от 0 до 99

getRandomInt(5, 5); // всегда 5, но формула всё равно работает

Генерация дробных чисел с точностью
Иногда нужно не целое число, а дробное — например, вероятность выпадения чего-то, плавающее значение в расчётах или просто скидка с двумя знаками после запятой. Для этого есть несколько способов.
Первый вариант самый простой. Чтобы получить любое дробное число в диапазоне, без контроля точности, используют базовую формулу:
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}

Работает отлично, но количество знаков после точки случайное и неудобное.
Второй способ — это формула с контролем точности. Если нам нужно, чтобы в результате было ровно 2 знака, или 3, или 4, то используется такая функция:
function getRandomFloat(min, max, decimals = 2) {
// Генерируем случайное число в диапазоне от min до max
const random = Math.random() * (max - min) + min;
// Округляем число до нужного количества знаков после запятой (в виде строки)
const str = random.toFixed(decimals);
// Преобразуем строку обратно в число с плавающей точкой и возвращаем
return parseFloat(str);
}
При вызове функции мы прописываем диапазон и количество знаков после запятой. Два знака:

Три знака:

Четыре знака:

Метод .toFixed() возвращает строку, поэтому используем parseFloat() или + перед ней, чтобы снова получить число. Такой способ проще и отлично подходит для несложных повседневных задач.
Примеры диапазонов (1–10, 0–100 и др.)
Мы уже разобрали, как получить случайное целое число с помощью getRandomInt(min, max) и как сгенерировать дробное число — простой способ и с заданной точностью через getRandomFloat(min, max, decimals). Во всех этих функциях мы явно задаём диапазон: от какого числа и до какого (min и max). А дальше — дело техники.
Ниже собрали набор готовых примеров для самых частых случаев из жизни:
// Целое от 1 до 10
getRandomInt(1, 10);
// Целое от 0 до 99
getRandomInt(0, 99);
// Только 0 или 1 (например, симуляция монетки: орёл или решка)
getRandomInt(0, 1);
// Целое от −10 до 35 (например, температура)
getRandomInt(-10, 35);
// Дробное от 0 до 1 (по сути, просто Math.random())
Math.random();
// Дробное от 5,5 до 7,8 с двумя знаками после запятой
getRandomFloat(5.5, 7.8, 2);
// Процент от 0 до 100 с двумя знаками
getRandomFloat(0, 100, 2);
// Рандомный час от 0 до 23
getRandomInt(0, 23);
Для целых чисел используем Math.floor() и +1, чтобы включить max. Для дробных — можно действовать через toFixed() и parseFloat, либо через множитель (как в getRandomFloat).
Практическое применение
Сила Math.random() раскрывается, когда вы добавляете к нему немного логики: выбираете элемент из массива, красите фон, бросаете виртуальные кости или генерируете моковые айдишники.
Случайный выбор элемента из массива
Допустим, у нас есть массив и мы хотим вытащить из него случайный элемент. Неважно, что внутри: цитаты, картинки, цвета, еда на ужин.
Например, есть массив с едой:
const items = [‘🍕’, ‘🍔’, ‘🍣’, ‘🌮’, ‘🥗’];
Берём Math.random(), умножаем на длину массива, округляем вниз — и получаем валидный индекс:
const randomItem = items[Math.floor(Math.random() * items.length)];
console.log(randomItem);

Работает везде: подходит для ротации баннеров, показа случайных отзывов или цитат, выбора цвета или фона.
Генерация случайного цвета (HEX, RGB)
Фронтендерам иногда задают на собеседованиях такую задачу — сделать генератор случайного цвета. Такой код можно реально использовать в жизни: для динамического изменения фона карточек, графиков, аватарок, анимаций и прочих визуальных штук. Вполне себе прикладная задача, которую легко показать на интервью, а потом использовать в проектах.
Цвет в вебе обычно представляют в двух форматах:
- HEX-формат — привычный #ff0022, короткий и используется почти везде.
- RGB-формат — rgb(255, 0, 34), читается лучше, удобно для плавных переходов и анимаций.
Какой вариант использовать — зависит от задач. Дальше посмотрим, как их сгенерировать с помощью Math.random().
Для генерации HEX-цвета можно воспользоваться такой формулой:
function getRandomHexColor() {
// Генерируем случайное число от 0 до 16777215 (в десятичной системе)
const hex = Math.floor(Math.random() * 0xffffff).toString(16);
// Преобразуем число в шестнадцатеричную строку и дополняем нулями слева, если длина меньше 6 символов
return `#${hex.padStart(6, '0')}`;
}
0xFFFFFF — это 16 777 215 в десятичной системе. Это максимальное значение для шестизначного HEX (#FFFFFF), то есть самого светлого цвета.
Цвет в формате HEX строится из трёх компонентов: красного (R), зелёного (G) и синего (B). Каждый из них занимает 8 бит и принимает значения от 0 до 255, то есть 256 возможных значений на канал.
Если посчитать все возможные комбинации: 256 (R) × 256 (G) × 256 (B), то мы получим 16 777 216 цветов. Но так как отсчёт начинается с нуля, самое первое значение — это 0x000000 (чёрный), а последнее — 0xFFFFFF (белый). То есть нам нужно получить случайное число от 0 до 16 777 215 включительно, что даст все 16 777 216 возможных цветов.
Вызываем нашу функцию и получаем случайный HEX-цвет:
console.log(getRandomHexColor());

Теперь напишем функцию для генерации случайного цвета в формате RGB:
function getRandomRgbColor() {
const r = Math.floor(Math.random() * 256); // от 0 до 255
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
Цвет в формате RGB тоже состоит из трёх компонентов: красного (R), зелёного (G) и синего (B). Каждый из них — это целое число от 0 до 255, что соответствует 8 битам данных. Получается те же 16 777 216 возможных цветов, как и в HEX, просто записываются по-другому:
- HEX: #FF8040
- RGB: rgb(255, 128, 64)
Дальше мы вызываем Math.random() для каждого канала отдельно, умножаем на 256, округляем вниз и получаем целое число в нужном диапазоне.Теперь вызываем функцию — и получаем свеженький RGB-цвет в формате rgb(число, число, число), который можно сразу подставить в style.backgroundColor или в CSS:
console.log(getRandomRgbColor());

Создание простых игровых механик
Самое базовое, с чего часто начинают знакомство со случайностями, — это симуляция броска кубика. Идеально подходит для демо, тестов, да и просто чтобы оживить интерфейс. Здесь всё намного проще, чем с цветами, потому что есть всего 6 вариантов:
function rollDice() {
return Math.floor(Math.random() * 6) + 1;
}
Рассмотрим по шагам:
Math.random()выдаёт число от 0 до 0,999…- Умножаем его на 6, получаем диапазон от 0 до 5,999…
- Дальше
Math.floor()обрезает дробную часть и даёт 0–5. - +1 сдвигает диапазон в нужную сторону: от 1 до 6.
console.log(rollDice());

Вообще, в реальных проектах Math.random() почти никогда не используется напрямую — его оборачивают во вспомогательные функции:
getRandomInt(min, max)— для получения случайного числа в заданном диапазоне.chooseRandom(array)— для выбора случайного элемента.rollChance(probability)— например, шанс срабатывания скила или падения лута.
Потому что написать Math.random() * (max – min) + min легко. А вот написать это без ошибок на границах — это уже квест. Например, можно забыть +1, и max никогда не выпадет. Даже простые функции вроде «броска кубика» легко сломать на ровном месте, особенно если диапазоны нестандартные или логика чуть сложнее.
Поэтому нормальные разработчики (особенно в геймдеве) всегда оборачивают Math.random() во вспомогательные функции с понятным API, чтобы безопасно переиспользовать.
Генерация ID и случайных строк
Если нужно быстро сгенерировать случайный идентификатор, не устанавливая стороннюю библиотеку, то Math.random() может выручить. Это удобно, когда нам нужен временный ключ, мы создаём уникальные значения в прототипе, работаем с моковыми данными или просто решаем задачку на собеседовании.
Выглядит это так:
const id = Math.random().toString(36).substring(2, 10);
console.log(id);
В этом коде:
Math.random()даёт число от 0 до 1..toString(36)переводит его в буквенно-цифровой формат, используя цифры и латинские буквы..substring(2, 10)убирает“0.”и берёт 8 символов.
На выходе получаем короткую случайную строку, которую можно использовать как ID в моковых данных, ссылках, ключах и т. п.

⚠️Никогда не используйте Math.random() для генерации токенов, паролей, ключей API, сессий и другой чувствительной информации. Этот метод криптографически небезопасен и может быть предсказуем при атаке.
Альтернативы Math.random()
Как мы уже сказали выше, Math.random() хорош для простеньких игр, демо, UI‑тестов и прочих несекретных дел. Но если мы генерируем что-то чувствительное — токены доступа, пароли, ID для сессий или пользователей, одноразовые ссылки, — то Math.random() не подойдёт.
Crypto.getRandomValues() для криптографически безопасных чисел
Если нужно получить настоящие случайные числа, пригодные для безопасности, используйте встроенное в браузер API:
crypto.getRandomValues(typedArray);
Этот метод возвращает по‑настоящему случайные числа — такие, которые сложно предсказать или взломать. Он используется в браузерах и генерирует значения на основе разных системных данных: энтропии, шума, движений курсора и прочих низкоуровневых штук.
// Создаём массив, который будем заполнять
const array = new Uint32Array(4); // 4 случайных числа от 0 до 2^32 - 1
// Заполняем его крипторандомными значениями
crypto.getRandomValues(array);
// Вызываем и получаем массив из чисел
console.log(array);

Uint32Array — это специальный типизированный массив, в котором хранятся 32-битные целые числа. Метод crypto.getRandomValues() берёт этот массив и перезаписывает все его значения случайными числами.
Да, под капотом crypto.getRandomValues() тоже использует псевдослучайный генератор (PRNG) — но с правильным сидом и достаточной энтропией. Это не просто «рандом», а рандом, которому можно доверять.
Библиотеки для расширенной генерации
Иногда Math.random() или даже crypto.getRandomValues() — это слишком низкоуровнево. Хочется просто сказать: выдай мне ID, собери строку из 8 символов, но только буквы и цифры — и всё. Тогда используют сторонние библиотеки: они дают надёжность, читаемость и отсутствие ошибок в логике генерации.
Рассмотрим три самые популярные.
UUID
UUID — это универсальный уникальный ID в формате xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Часто используется в бэкенде, но и во фронтенде тоже пригодится: для временных ключей, мок-данных, ссылок, генерации разных элементов и прочих мест, где важна уникальность.
Если вы работаете с Node.js или пишете фронтенд со сборщиком (Webpack, Vite и т. п.), то ставите зависимость npm install uuid, а потом используете её в проекте:
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();
console.log(id); // Например: "b7bbf47c-1739-4f67-8d0f-168a12345abc"
Если нужно сгенерировать UUID на лету, например в консоли DevTools, на CodePen или в простом проекте, можно использовать встроенный метод:
let myuuid = crypto.randomUUID();
console.log('Your UUID is: ' + myuuid);

Это часть Web Crypto API, работает в безопасном контексте (https://, localhost) во всех современных браузерах.
Nano ID
Если нужно что-то более легковесное, то подойдёт генератор Nano ID. Он весит всего 118 байт, использует расширенный алфавит A–Z, a–z, 0–9, _, и за счёт этого короче, чем UUID, но так же надёжен.
Устанавливаем через npm install nanoid и дальше импортируем в проект:
import { nanoid } from 'nanoid';
const id = nanoid();
console.log(id); // Например: "V1StGXR8_Z5jdHi6B-myT"
Можно задать длину ID или использовать собственный алфавит. Подойдет для генерации ID для DOM‑элементов, списков, UI‑объектов, ссылок или временных ключей.
faker-js
Библиотека @faker-js/faker — это целая экосистема для генерации любых фейковых данных: имён, адресов, компаний, мейлов и прочего. Но нас интересует генерация случайных чисел. Чтобы каждый раз не писать формулы для Math.random, в faker.number есть удобный API для генерации каких угодно чисел.
Устанавливаем через npm install @faker-js/faker и импортируем в проект:
import { faker } from '@faker-js/faker';
// Целое число от 0 до 100
const randomInt = faker.number.int({ min: 0, max: 100 });
// Дробное число от 1,5 до 5,5 с точностью до сотых
const randomFloat = faker.number.float({ min: 1.5, max: 5.5, precision: 0.01 });
Если у вас большой проект с моками, тестами, автогенерацией интерфейсов, то faker может заменить кучу ручного кода и дать единый источник фейковых данных. Но если нужно просто сгенерировать пару чисел — возможно, проще обойтись Math.random() или чем-то полегче.
Частые ошибки и вопросы
Почему Math.random() не совсем случайный
Как мы уже говорили, в этом методе используется псевдослучайный генератор — PRNG (Pseudo-Random Number Generator). Он просто выполняет алгоритм, который даёт последовательность чисел, выглядящих случайными.
Алгоритм работает на базе начального значения, сида. В других языках можно задать сид самостоятельно и получить одинаковые результаты при каждом запуске (например, random.seed(5) в Python). В JS — такой возможности нет. Сид задаётся изнутри, и доступа к нему нет.
А почему вообще так? И почему это до сих пор не исправили?
Один из разработчиков JScript (движка JS в IE) так объяснял это решение: «В 90-х JavaScript создавался, чтобы заставить обезьянку на экране танцевать, когда двигаешь мышку. Никто не собирался писать на нём сложные системы, а уж тем более использовать криптографию».
Кроме того, тогда действовали жёсткие законы: криптография официально считалась военной технологией, и её «экспорт» в браузерах мог вызвать юридические проблемы. Поэтому Math.random() сделали простым и «безопасным» в смысле законодательства, а не криптографии.
Сегодня пересобрать это поведение уже нельзя, потому что это нарушит совместимость и может ввести в заблуждение (вроде бы Math.random() стал криптостойким, а на деле — нет). Поэтому Math.random() таким и остался: удобным, быстрым, но не для задач, где важна безопасность или уникальность.
Как избежать повторяющихся последовательностей
Если вы генерируете много значений подряд, особенно в короткий промежуток времени, может показаться, что числа повторяются или слишком «похожие». Это не баг, а особенность PRNG: иногда он реально выдаёт почти одинаковые числа.

Чтобы избежать этого, делают так:
- Используют вспомогательные обёртки:
getRandomInt,getRandomFloat,shuffleArray. - Добавляют перемешивание: алгоритм Фишера — Йетса или другие.
- Для максимального разнообразия используют
crypto.getRandomValues()или сторонние библиотеки.
Даже в случайности нужна логика: если вы, например, делаете генератор лутбоксов и хотите, чтобы приз точно не повторился, — нужно вести список того, что уже выпало, и исключать это вручную. Math.random() сам этого не сделает.
Какие есть ограничения в плане безопасности случайных чисел
И вот тут повторим: Math.random() — это удобный, но небезопасный способ генерации чисел. Он не годится для токенов доступа, паролей, сессионных ключей, генерации важных уникальных ID, любых операций, где есть риск предсказуемости и атаки.
Алгоритм можно предугадать, если знать исходное состояние, и он не защищён от перебора или анализа. Это не теория — есть реальные атаки, основанные на слабости генератора случайных чисел.
Например, в 2025 году была найдена критическая уязвимость (CVE‑2025‑7783) в популярной npm-библиотеке form-data, которая использовала Math.random() для генерации multipart boundary — специальной строки-разделителя в HTTP-запросах. Поскольку Math.random() предсказуем, атакующий мог вычислить эти границы и внедрить свои данные в запрос, обходя валидацию. Это приводило к выполнению произвольного кода и другим критическим проблемам безопасности.
Вывод? Если вы работаете с чем-то, где «случайность» влияет на безопасность — обязательно используйте криптоустойчивые методы.
Вам слово
Приходите к нам в соцсети поделиться своим мнением о статье и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!


