Что не так с "корейским рандомом"?

инициализируя std::random_device
Да, этот вариант предпочтительней, но он появился только в C++11, поэтому в GF и использовали QueryPerformanceCounter(ведь счётчик тактов - корректный источник энтропии).

В своих фиксах для С1 я тоже переписал rand() на std::mt19937
Как мне кажется, главная проблема - это всё же использование остатка от деления для установки диапазона.
И, как я уже показал выше, в GF её решили довольно элегантно. Вот для наглядности:

std::mt19937_64 генерирует целые числа в диапазоне [0, (2^64)-1] (0x0000000000000000, 0xFFFFFFFFFFFFFFFF).
Для получения double числа используются только 53 бита (0x001FFFFFFFFFFFFF) (количество неслучайно: связано с шириной мантиссы double).
Далее идёт умножение на один из постоянных double множителей:
DOUBLE_UNIT_EXCLUSIVE = 1.1102230246251565e-016 (0x3CA0000000000000)
или
DOUBLE_UNIT_INCLUSIVE = 1.1102230246251568e-016 (0x3CA0000000000001)
(оба они примерно равны 0.00000000000000011).

После преобразования ряды выглядят так:
C++:
(double)0x0000000000000000 * DOUBLE_UNIT_EXCLUSIVE  = 0.00000000000000000
(double)0x0000000000000001 * DOUBLE_UNIT_EXCLUSIVE ~= 0.00000000000000011
(double)0x0000000000000002 * DOUBLE_UNIT_EXCLUSIVE ~= 0.00000000000000022
...
(double)0x001FFFFFFFFFFFFD * DOUBLE_UNIT_EXCLUSIVE ~= 0.99999999999999967
(double)0x001FFFFFFFFFFFFE * DOUBLE_UNIT_EXCLUSIVE ~= 0.99999999999999978
(double)0x001FFFFFFFFFFFFF * DOUBLE_UNIT_EXCLUSIVE ~= 0.99999999999999989
C++:
(double)0x0000000000000000 * DOUBLE_UNIT_INCLUSIVE  = 0.00000000000000000
(double)0x0000000000000001 * DOUBLE_UNIT_INCLUSIVE ~= 0.00000000000000011
(double)0x0000000000000002 * DOUBLE_UNIT_INCLUSIVE ~= 0.00000000000000022
...
(double)0x001FFFFFFFFFFFFD * DOUBLE_UNIT_INCLUSIVE ~= 0.99999999999999989
(double)0x001FFFFFFFFFFFFE * DOUBLE_UNIT_INCLUSIVE ~= 1.00000000000000000
(double)0x001FFFFFFFFFFFFF * DOUBLE_UNIT_INCLUSIVE  = 1.00000000000000000
На всём протяжении ряды отличаются абсолютно незначительно, важно лишь максимально возможное значение.
В итоге получается 2^53 double значений в диапазоне от 0.0 до 1.0 (проще говоря от 0% до 100%) c шагом ~0.00000000000000011.
 

Назад
Сверху Снизу