JavaScript - это диалект ECMAScript. Стандарт ECMAScript-262 не может точно указать Math.random
. В пункте 20.2.2.7 говорится:
20.2.2.27 Math.random ()
Возвращает числовое значение с положительным знаком, большим или равным 0, но меньшим 1, выбранным случайным или псевдослучайным образом с приблизительно равномерным распределением по этому диапазону, используя алгоритм или стратегию, зависящие от реализации. Эта функция не принимает аргументов.
Каждая функция Math.random , созданная для различных областей, должна генерировать определенную последовательность значений из последовательных вызовов.
В отсутствие полной спецификации невозможно сделать однозначное утверждение относительно вероятности того, что Math.random
вернет ноль. Каждая реализация ECMAScript может выбирать разные алгоритмы и не должна обеспечивать действительно равномерное распределение.
ECMAScript использует базовый 64-битный двоичный формат IEEE-754 для своего типа Number
. В этом формате значимое (дробная часть) числа имеет 53 бита. Каждое число с плавающей точкой имеет вид s • f • 2 e , где s (для знака ) равен +1 или -1, f (для дробной части) - значение и целое число в [0, 2 53 ) и e (для экспонента) представляет собой целое число в [−1074, 971]. Число считается нормализованным, если установлен старший бит f (поэтому f находится в [2 52 , 2 53 )). Так как отрицательные числа не имеют значения в этом ответе, пусть s будет неявно +1 для остальной части этого ответа.
Одна проблема с распределением случайных чисел в [0, 1) заключается в том, что представимые значения не расположены равномерно. Существует 2 52 представимых значений в [½, 1) - все они с f в [2 52 , 2 53 ) и e = −53. И в [¼, ½) одинаковое количество значений - все они с f в [2 52 , 2 53 ) и e = −54. Поскольку в этом интервале одинаковое количество чисел, но интервал вдвое меньше, числа расположены ближе друг к другу. Аналогично, в [⅛, ¼) расстояние снова уменьшается вдвое. Это продолжается до тех пор, пока показатель не достигнет -1074, после чего нормальные числа оканчиваются на f = 2 52 . Числа, меньшие, чем это, называются субнормальными (или нулевыми), с f в [0, 2 52 ) и e = -1074, и они равномерно расположены.
Один из способов распределения чисел для Math.random
заключается в использовании только набора равномерно распределенных чисел f • 2 −53 для f в [0, 2 53 ). При этом используются все представимые значения в [½, 1), но только половина значений в [¼, ½), четвертая часть значений в [⅛, ¼) и т. Д. Это просто и позволяет избежать некоторых странностей в распределении. При правильной реализации ноль вероятности равен единице в 2 53 .
Другой вариант - использовать все представимые значения в [0, 1), каждое из которых имеет вероятность, пропорциональную расстоянию от него до следующего более высокого представимого значения. Таким образом, каждое представимое число в [½, 1) будет выбрано с вероятностью 1/2 53 , каждое представимое число в [¼, ½) будет выбрано с вероятностью 1/2 54 , каждое представимое число в [⅛, ¼) будет выбрано с вероятностью 1/2 55 и т. д. Это распределение приближается к равномерному распределению по реалам и поставщикам с более высокой точностью, где формат с плавающей точкой является более точным. При правильной реализации ноль вероятности равен единице в 2 1074 .
Другой вариант - использовать все повторы.resentable значения в [0, 1), каждое с вероятностью, пропорциональной длине сегмента, в котором представимое значение является ближайшим представимым значением всех действительных чисел в сегменте. Я опущу обсуждение некоторых деталей этого распределения, за исключением того, что оно имитирует результаты, которые можно получить, выбрав действительное число с равномерным распределением, а затем округлив его до представимого значения с использованием правила округления до ближайших связей к четным. , При правильной реализации ноль вероятности равен единице из 2 1075 . (Одна проблема с этим распределением состоит в том, что равномерное распределение по действительным значениям в [0, 1) иногда дает число, настолько близкое к 1, что при округлении получается 1. Для этого требуется либо, чтобы Math.random
было разрешено возвращать 1, либо что Распределение можно обмануть каким-то образом, возможно, возвращая следующее более низкое представимое значение вместо 1.)
Отмечу, что спецификация ECMAScript достаточно слаба, и можно утверждать, что Math.random
может распределять числа с равной вероятностью для каждого представимого значения, игнорируя интервал между ними. Это вовсе не имитирует равномерное распределение по реальным числам, и я ожидаю, что очень немногие одобрили бы это. Однако, если реализовано, возвращается ноль вероятности, равный единице в 1021 • 2 52 , потому что есть 2 52 нормализованных чисел с показателями от -53 до -1074 (1020 значений e ) и 2 52 ненормальных или нулевых чисел.