Нажимаете кнопку, появляется число, и предполагается, что оно случайно. Стоит спросить, что его породило, — потому что один из двух ответов проверяем, а другой нет.
Откуда берётся настоящая случайность
Настоящая случайность берётся из физических процессов, не определяемых предшествующим состоянием:
- Радиоактивный распад — точный момент распада атома предсказать нельзя
- Тепловой шум — случайные колебания напряжения в резисторе
- Атмосферный шум — фоновые помехи от грозовой активности
- Квантовое измерение — исходы, которые действительно неопределённы
Это не приближения случайности. Они случайны в том смысле, что никакое знание о прошлом не определяет исход.
Что делает компьютер вместо этого
Компьютер не может наблюдать ничто из этого напрямую, поэтому аппаратный генератор считывает их. Необработанные байты поступают откуда-то вроде /dev/urandom или эквивалентного источника операционной системы, который сам инициализируется физическими процессами. Это истинный генератор случайных чисел.
Гораздо более частый случай — генератор псевдослучайных чисел: детерминированный алгоритм, порождающий последовательность, которая лишь выглядит случайной.
next = (previous × multiplier + increment) mod modulus
Ключевое свойство очевидно. Если вы знаете алгоритм и зерно, вы можете вычислить каждое значение, которое когда-либо выдаст последовательность. Не приблизительно — точно.
Именно поэтому Math.random(), который использует почти каждый сайт, непригоден для всего, что имеет значение. Его результат определяется внутренним состоянием. Восстановите это состояние по наблюдаемым значениям — и каждый будущий бросок станет предсказуемым.
Самый часто приводимый пример: полное состояние линейного конгруэнтного генератора можно восстановить по нескольким последовательным значениям. Mersenne Twister, используемый в Python по умолчанию, требует 624 значения для реконструкции — а 624 набирается за секунды.
Xorshift и подобные быстрые генераторы обладают тем же свойством в другой форме: превосходное статистическое качество, но полная предсказуемость, если у вас есть состояние.
Промежуточный вариант, который действительно важен
Это та часть, которую большинство объяснений пропускает, и именно она решает ответ на практике.

Современные веб-платформы не используют «сырой» /dev/urandom при каждом вызове. Они применяют криптографически стойкий ГПСЧ — детерминированный алгоритм, но инициализируемый аппаратной энтропией и устроенный так, что наблюдение за результатами не позволяет восстановить состояние.
В этом различии стоит быть точным, потому что эти два понятия путают:
| Аппаратный TRNG | CSPRNG | Обычный ГПСЧ | |
|---|---|---|---|
| Основан на физической энтропии | Да | Да | Нет |
| Детерминирован при известном состоянии | Нет | Да | Да |
| Результат раскрывает состояние | Нет | Нет | Да |
| Подходит для розыгрыша призов | Да | Да | Нет |
CSPRNG детерминирован в том же смысле, в каком детерминировано любое используемое вами ПО. Приемлемым его делает то, что состояние нельзя восстановить по уже выданным значениям.
Браузеры предоставляют именно это через crypto.getRandomValues(). Это источник, из которого черпает RandomSelect.
Честность — второй вопрос
Равномерность легко нарушить даже с хорошим источником. Для d6 всё просто: шесть равновероятных значений. Для d7 — уже нет, как и для «выбери 1 из 40 имён».
Наивный подход — масштабирование случайного числа с плавающей точкой от 0 до 1 на диапазон — смещает результат к началу. При 40 именах первое выпадало бы чуть чаще последнего, потому что некоторые случайные значения выходят за границу последней корзины и отбрасываются неравномерно.
Правильный подход — выборка с отбраковкой: тяните значение, и если оно попадает в неполную последнюю корзину, отбросьте его и тяните снова. Распределение становится строго равномерным.
Это легко упустить, потому что смещение мало. На практике реализация отбрасывает значения вне диапазона и тянет заново, поэтому у каждой записи ровно шанс 1/N — в том числе при выборе из 40 имён, где реализация с масштабированием дала бы первому имени чуть более высокую вероятность.
Та же техника используется в генераторе коротких идентификаторов, где комментарий в коде отмечает долю принятых значений и итоговое смещение — около двух частей на десять миллионов. Достаточно мало, чтобы не иметь значения, и достаточно мало, чтобы небрежная реализация осталась незамеченной, — в этом и смысл измерения.
Что это значит на практике
Для выбора обеда всё это не важно. Любой генератор выдаст приемлемый обед.
Для розыгрыша призов, распределения сотрудников или чего-либо, связанного с репутацией, вопрос в том, можно ли было предугадать результат. С Math.random() — в принципе да. С crypto.getRandomValues() — нет, а это разница между «мы говорим, что это случайно» и «механизм делает это таковым».
Есть связанный и часто путаемый момент об анимации. На вращающемся колесе результат фиксируется до того, как колесо начинает движение; анимация проигрывается к нему. Некоторые читатели принимают это за доказательство манипуляции. Всё наоборот: поскольку исход уже определён и не может быть изменён моментом остановки, нет входных данных, которыми кто-либо мог бы воспользоваться. Визуальная часть — это представление вокруг уже зафиксированного значения.
Проверьте сами
Простое упражнение, не требующее кода: бросьте кубик двадцать раз и запишите результаты. Затем поищите серии.
Вы их найдёте. Три шестёрки подряд случаются примерно раз на каждые пятьдесят бросков. Это не признак того, что кубик нечестный, — так и выглядит честный процесс, когда рассматриваешь короткую выборку.
Затем бросьте сто раз и посчитайте каждую грань. Разрывы сужаются. Никто ни к чему не сходится, потому что и не было недостатка, который нужно закрывать: вот что означает независимость, если присмотреться достаточно внимательно.
Где читать дальше
Страница честности на этом сайте разбирает фактическую реализацию, включая шаг выборки с отбраковкой. Её стоит прочитать один раз, особенно если вы выбираете инструмент для решения, которое будут оспаривать.
Практический итог короток: инструмент, который использует crypto.getRandomValues() и отбрасывает значения вне диапазона, делает всё правильно, и вам не нужно верить ему на слово — вы можете рассуждать о механизме.