Какой алгоритм подавать в объект распределения вероятности в Random? C++

В заголовочном файле random присутствуют объекты, как я понял, отвечающие за распределение генерированных случайных чисел. Например uniform_int_distribution. Так вот в чем отличие этих алгоритмов от алгоритмов генерации случайных чисел? Зачем им в операторе () нужно подавать генератор и как понять какой именно требуется? Например:

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distrib(0, 100);

Зачем здесь нужен mt19937 генератор? И почему нельзя использовать другой?


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

Автор решения: HolyBlackCat

Генератор (например std::mt19937) генерирует случайные биты. В случае std::mt19937 биты идут пачками по 32, в std::uint32_t. Один набор случайных бит можно получить, вызвав на генераторе operator() без параметров.

Классы распределений (distribution-ы) из случайных бит делают случайные числа - в конкретном диапазоне, с определенным распределением (равномерным, или еще каким-то).

В принципе можно обойтись без классов распределений. Можно написать просто gen() % 101, но крутые дядьки так не делают, потому что распределение получится немного неравномерным.

Зачем здесь нужен mt19937 генератор? И почему нельзя использовать другой?

Можно и другой. Генераторы имеют разное качество случайных чисел и разную скорость работы. Как-то традиционно из <random> используют std::mt19937 - видимо выдает достаточно качественный рандом достаточно быстро.

std::random_device - это тоже генератор. Ему не нужен seed, и по задумке он выдает "по-настоящему рандомные" числа, платформо-зависимым способом. Обычно его не используют напрямую из-за скорости. Обратите внимание, что он был сломан в MinGW (починен в версии GCC 9.2) - при каждом запуске программы выдавал одни и те же числа.

Еще обратите внимание, что от std::mt19937 можно добиться более качественного рандома, инициализируя его другим способом, например как тут. Вы ему на вход даете только 32 рандомных бита, а по-хорошему ему нужно 19937 бит.

→ Ссылка