Как кратко, портативно и тщательно заполнить PRNG mt19937?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как кратко, портативно и тщательно заполнить PRNG mt19937?

Сообщение Anonymous »

Кажется, я вижу много ответов, в которых кто-то предлагает использовать для генерации случайных чисел, обычно вместе с таким кодом:

Код: Выделить всё

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution dis(0, 5);
dis(gen);
Обычно это заменяет какую-нибудь «нечестивую мерзость», например:

Код: Выделить всё

srand(time(NULL));
rand()%6;
Мы могли бы критиковать старый способ, утверждая, что time(NULL) обеспечивает низкую энтропию, time(NULL) предсказуем, а конечный результат неоднороден.

Но все это верно и для нового способа: он просто имеет более блестящую оболочку.
  • возвращает одно целое число без знака. Он имеет как минимум 16 бит, а возможно и 32. Этого недостаточно для заполнения 19937 бит состояния MT.
  • Использование std::mt19937 gen(rd());gen() (заполнение 32 битами и просмотр первого вывода) не дает хорошего распределения вывода. 7 и 13 никогда не могут быть первым выходом. Два семени дают 0. Двенадцать семечек дают 1226181350. (Ссылка)
  • Код: Выделить всё

    std::random_device
    может быть, а иногда и реализуется, как простой PRNG с фиксированным начальным значением. Поэтому он может создавать одну и ту же последовательность при каждом запуске. (Ссылка) Это даже хуже, чем time(NULL).
Хуже того, очень легко скопировать и вставить приведенные выше фрагменты кода, несмотря на содержащиеся в них проблемы. Некоторые решения этой проблемы требуют приобретения больших библиотек, которые могут подойти не всем.

В свете этого мой вопрос: Как можно кратко, портативно и тщательно заполнить PRNG mt19937 в C++?

Учитывая вышеизложенные проблемы, хороший ответ:
  • Необходимо полностью заполнить mt19937/mt19937_64.
  • Невозможно полагаться исключительно на std::random_device или time(NULL) в качестве источника энтропии.
  • Не следует полагаться на Boost или другие библиотеки.
  • Должен вписываться в небольшое количество строк, чтобы это выглядело красиво при копировании в ответ.
Мысли
  • Моя текущая мысль заключается в том, что выходные данные std::random_device могут быть объединены (возможно, с помощью XOR) с временем (NULL), значениями, полученными в результате рандомизации адресного пространства, и жестко закодированной константой (которая может быть установлена во время распределения), чтобы получить лучший способ добиться энтропии.
  • Код: Выделить всё

    std::random_device::entropy()
    не дает четкого представления о том, что может или не может делать std::random_device.


Подробнее здесь: https://stackoverflow.com/questions/450 ... 19937-prng
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»