Почему runif() имеет меньше уникальных значений, чем rnorm()?

Если вы запустите код, например:

length(unique(runif(10000000)))
length(unique(rnorm(10000000)))

вы увидите, что только около 99,8% значений runif уникальны, но 100% значений rnorm. Я думал, что это может быть из-за ограниченного диапазона, но увеличение диапазона до (0, 100000) для runif не изменяет результат. Непрерывные распределения должны иметь вероятность повторений = 0, и я знаю точность с плавающей точкой, но это не так, но мне любопытно, почему мы не видим достаточно близких к тому же количеству повторений между ними.

Ответ 1

Это связано прежде всего с свойствами PRNG по умолчанию (тот факт, что runif имеет меньший диапазон, чем rnorm и поэтому меньшее количество представимых значений также может иметь аналогичный эффект в какой-то момент, даже если RNG не работает). Это обсуждается несколько наклонно в ?Random:

Не полагайтесь на случайность младших разрядов от RNG. Большинство поставляемых однородных генераторов возвращают 32-битные целочисленные значения, которые преобразуются в двойные, поэтому они берут не более 2 ^ 32 различных значений, а длинные прогоны возвращают повторяющиеся значения (исключение составляет Wichmann-Hill, и все они дают как минимум 30 переменных бит.)

Пример:

sum(duplicated(runif(1e6))) # around 110 for default generator
## and we would expect about almost sure duplicates beyond about
qbirthday(1 - 1e-6, classes = 2e9) # 235,000

Переход к генератору Вихмана-Хилла действительно уменьшает вероятность дублирования:

RNGkind("Wich")  
sum(duplicated(runif(1e6)))
[1] 0
sum(duplicated(runif(1e8)))
[1] 0

Ответ 2

Документация для генерации случайных чисел гласит:

Не полагайтесь на случайность младших разрядов от RNG. Большинство поставляемых однородных генераторов возвращают 32-битные целочисленные значения, которые преобразуются в двойные, поэтому они берут не более 2 ^ 32 различных значений, а длинные прогоны возвращают повторяющиеся значения (исключение составляет Wichmann-Hill, и все они дают как минимум 30 переменных бит.)

По парадоксальности дня вы ожидаете увидеть повторяющиеся значения в наборе более чем примерно 2 ^ 16 значений и 10000000> 2 ^ 16. Я не нашел ничего прямо в документации о том, сколько возвращаемых значений будет возвращено rnorm, но оно предположительно больше 2 ^ 32. Интересно отметить, что set.seed имеет различные параметры kind, который определяет равномерную генератор и normal.kind, который определяет нормальный генератор, так что последний не простое преобразование прежнего.