Генерация случайных целых и действительных чисел в заданном диапазоне - PullRequest
3 голосов
/ 03 февраля 2020

Согласно справочной странице getNext в модуле PCGRandom , мы можем генерировать случайные числа в заданном диапазоне, например:

use Random;

var rng1 = new owned RandomStream( eltType= real, seed= 100 );
var rng2 = new owned RandomStream( eltType= int,  seed= 100 );

for i in 1..5 do
    writeln( rng1.getNext( min= 3.0, max= 5.0 ) );

writeln();
for i in 1..5 do
    writeln( rng2.getNext( min= 20, max= 80 ) );

, что дает (с chpl-1.20.0):

4.50371
4.85573
4.2246
4.84289
3.63607

36
57
79
39
57

Здесь я заметил, что страница man дает следующие примечания как для целых, так и для действительных чисел:

Для целые числа, этот класс использует стратегию для генерации значения в определенном диапазоне, который не подвергался тщательному изучению, и может иметь статистические проблемы .

Для действительных чисел этот класс генерирует случайное число значение в [max, min] путем вычисления случайного значения в [0,1], масштабирования и сдвига этого значения. Обратите внимание, что не все возможные значения с плавающей запятой в интервале [min, max] могут быть построены таким образом .

(где я выделил курсивом). Для действительных чисел это связано с так называемой «плотностью числа с плавающей точкой», например, задаваемой в на этой странице )? Кроме того, для целых чисел, есть ли какой-то случай, который нам нужно соблюдать осторожность даже для «типичного» использования? (здесь «типичный» означает, например, генерацию 10 ** 8 случайных целых чисел, распределенных приблизительно плоско в заданном диапазоне.)

К вашему сведению, мой «сценарий использования» не похож на строгие качественные тесты для случайных числа, но только типичные вычисления Монте-Карло (например, выбор случайных сайтов на решетке кубических c).

1 Ответ

3 голосов
/ 03 февраля 2020

Примечания на странице руководства указывают на отличие от других методов случайных чисел PCG, которые были изучены (по крайней мере, автором алгоритма PCG).

Проблема с плавающей запятой числа действительно связаны с плотностью числа с плавающей точкой. См. http://www.pcg-random.org/using-pcg-c-basic.html#generating - удваивается от автора PCG. Это потенциальная проблема даже при генерации случайных чисел в [0.0, 1.0]. В этом абзаце из документации описывается проблема:

При создании действительного, мнимого или комплексного числа в этой реализации используется стратегия генерирования 64-разрядного целого числа без знака, а затем умножения его на 2,0 ** -64, чтобы преобразовать его в число с плавающей запятой. Хотя это создает равномерное распределение по округленным значениям с плавающей запятой, оно исключает множество возможных реальных значений (например, 2 ** - 128). Мы считаем, что эта стратегия обладает разумными статистическими свойствами. Одним из побочных эффектов этой стратегии является то, что реальное число 1.0 может быть сгенерировано из-за округления. Вещественное число 0.0 может быть сгенерировано, потому что PCG может выдавать значение 0 как случайное целое число.

Обратите внимание, что 64-разрядное действительное число может хранить числа, такие как 2.0**-1024, но это совершенно невозможно получить такое число, разделив положительное целое число на 2**64. (Здесь и выше я использую ** в качестве оператора возведения в степень, поскольку это то, что он делает в синтаксисе часовни). Я рекомендую ознакомиться с форматами IEEE с плавающей запятой (например, https://en.wikipedia.org/wiki/IEEE_754 или https://en.wikipedia.org/wiki/Double-precision_floating-point_format) для получения справочной информации в этой области. Вас это может беспокоить, если вы использовали RNG для генерации тестовых входных данных для алгоритма, работающего со значениями real(64). В этом случае вы могли бы получить sh даже для очень маленьких значений, которые будут сгенерированы. Обратите внимание, что построение ГСЧ, который может генерировать все значения real(64) неоднородным образом, не так сложно (например, просто путем копирования битов из uint в real).

Относительно другая часть вашего вопроса:

Я провел базовое c статистическое тестирование с генерацией случайных целых чисел в определенном диапазоне с TestU01, и я был бы уверен в его использовании с вычислениями Монте-Карло. Однако я не эксперт в этой области, и в результате я добавил это предупреждение в документацию. Приведенная ниже информация из документации описывает тестирование, которое я провел:

Мы протестировали эту реализацию с TestU01 (доступно по http://simul.iro.umontreal.ca/testu01/tu01.html). Мы измерили нашу реализацию с TestU01 1.2.3 и набором Cru sh, который состоит из 144 статистических тестов. Результатами были:

  • без сбоев при генерации унифицированных реалов
  • 1 сбоев при генерировании 32-битных значений (что также верно для эталонной версии PCG с той же конфигурацией)
  • 0 сбоев для генерации 64-битных значений (которые мы предоставили TestU01 как 2 разных 32-битных значения, поскольку он принимает только 32 бита за раз)
  • 0 сбоев для генерации ограниченных целых чисел (которые мы предоставили TestU01, запрашивая значения в [0..,2**31+2**30+1), пока у нас не было двух значений <2 ** 31, удалив верхний 0 бит и затем объединили верхние 16 бит в значение, предоставленное TestU01). </li>
...