Генерация случайных чисел

Генерация случайных чисел

Технический фундамент случайности в JS

Math.random() дает не «истинно случайное», а псевдослучайное число. Это означает:

  • значения выглядят случайными для прикладных задач;
  • результат определяется внутренним алгоритмом генератора;
  • для security-задач такой генератор не подходит.

Фундаментальный принцип: четко отделяй «UI/игровую случайность» от «криптографической случайности».

Почему тема случайности важна

Случайные числа в JavaScript нужны для большого количества практических задач: выбор случайного баннера, генерация тестовых данных, случайная выдача карточек, имитация броска кубика, простые игровые механики.

Базовый инструмент — Math.random(), но с ним важно правильно работать, иначе диапазон будет неверным.

Что именно возвращает Math.random

console.log(Math.random());

Результат всегда в диапазоне [0, 1): от 0 включительно до 1 не включительно.

Ключевой момент: 1 метод не возвращает никогда. Это важно при формулах диапазона.

Проверь себя: почему диапазон именно полуоткрытый [0, 1), а не [0, 1]?

Подсказка: так проще получать корректные индексы/границы. Например, Math.floor(Math.random() * items.length) гарантированно даст индекс 0..items.length - 1. Если бы Math.random() мог вернуть 1, иногда получался бы индекс items.length (выход за границы).

Правильная формула для целого диапазона

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

Если ты хочешь число от 1 до 6 (кубик):

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

Здесь часто ошибаются:

  • забывают +1 в формуле и теряют верхнюю границу;
  • не используют Math.floor и получают дробные значения.

Смотри, что важно: для целых диапазонов почти никогда не используют Math.round(...) — он дает перекос вероятностей на границах.

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

В этой формуле крайние значения (min и max) получаются реже, чем середина.

Если тебе нужен случайный дробный диапазон, формула проще:

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

Случайный элемент массива

function pickRandomItem(items) {
  if (items.length === 0) return undefined;
  const index = Math.floor(Math.random() * items.length);
  return items[index];
}

Это базовый паттерн для случайного выбора вопроса в викторине или карточки товара на главной.

Что будет при некорректных входах

console.log(getRandomInt(10, 5));

Если min > max, формула математически ломается. Анти-провал: всегда валидируй вход перед генерацией.

function safeRandomInt(min, max) {
  if (!Number.isInteger(min) || !Number.isInteger(max) || min > max) {
    throw new Error('Некорректные границы диапазона');
  }
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Безопасность

Очень важно: Math.random() не криптографически безопасен. Для токенов, паролей и security-ключей используй crypto API.

Например:

// В Node.js:
// const { randomInt, randomUUID } = require('node:crypto');
// console.log(randomInt(1, 7)); // 1..6
// console.log(randomUUID());

// В браузере:
// console.log(crypto.randomUUID());

Микро-сценарии

  1. Показ случайного приветственного сообщения.
  2. Генерация тестовой оценки в диапазоне 0..100.
const score = getRandomInt(0, 100);
  1. Нормализация диапазона, если границы переданы в обратном порядке.
function getRandomIntNormalized(a, b) {
  const min = Math.min(a, b);
  const max = Math.max(a, b);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Типичные ошибки

  • Использовать неправильную формулу диапазона.
  • Игнорировать пустой массив при случайном выборе.
  • Путать генерацию целого и дробного случайного числа.
  • Применять Math.random в задачах безопасности.

Краткий итог

  • Math.random() дает число в диапазоне [0, 1).
  • Для целых значений нужна формула с Math.floor.
  • Выбор случайного элемента строится через случайный индекс.
  • Входные границы важно валидировать.
  • Для security-задач нужен не Math.random, а crypto.