Как использовать ГСЧ с++11 в классе?

random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> rng(1, 2);

Имеется такой генератор, находится он в main. Как я могу использовать этот генератор в виде int a = rng(gen) в классе? В заголовочный файл я не могу вставить в таком виде, в исполняемый вставляется, но правильно ли я использую его? введите сюда описание изображения в данном случае у меня есть еще 3 метода класса, где мне надо число генерировать случайно, это получается, что эти 3 строчки пишутся 3 раза, но я на 90% уверен, что это делается не так. Мне нужно передавать в конструктор класса этот генератор или как?


Ответы (1 шт):

Автор решения: Swift - Friday Pie

Разберемся по порядку.

 random_device rd;

Это - источник случайности, т.н. "зерна". По сути дела это генератор псевдослучайной последовательности целых чисел c равномерным распределением, в большинстве реализаций имеющи предетеминированное начало.

 mt19937 gen(rd());

Это наш ГСЧ, в данном случае тип mt19937 - "Вихрь" Мерсенна Выражение rd() - это "зерно", seed для генератора ПСЕВДОслучайных чисел. Передача его таким образом обычно делает его предсказуемым, чаще к зерну добавляют время или другие внешние факторы. Например:

std::mt19937::result_type seed = rd() ^ (
        (std::mt19937::result_type)
        std::chrono::duration_cast<std::chrono::seconds>(
            std::chrono::system_clock::now().time_since_epoch()
            ).count() +
        (std::mt19937::result_type)
        std::chrono::duration_cast<std::chrono::microseconds>(
            std::chrono::high_resolution_clock::now().time_since_epoch()
            ).count() );

std::mt19937 gen(seed);

Почему генератор по умолчанию был полностью детерминирован? В целях отладки и тестирования, ситуация та же что и со старинными srand\rand. Например, в новых версиях GCC (> 9.2) random_device был "исправлен" и вышеуказанная "рандомизация" может быть лишней. И, наконец,

 uniform_int_distribution<> rng(1, 2);

Это функция распределения. Можно иметь несколько генреаторов с различными зернами но использовать функции распределения с любым из них. ГСЧ хранит свое предыдущиее состояние, поэтому для независимых событий стоит использовать отдельные генераторы, но распределения можно использовать повторно. Выражение rng(gen) возвращает новое значения распределения rng для генератора gen.

→ Ссылка