Предположим, вы хотите использовать средства C ++ <random>
в практической программе (для некоторого определения «практический» - ограничения здесь являются частью этого вопроса). У вас есть код примерно так:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
У меня вопрос, какой тип вы должны использовать ENGINE
?
Раньше я всегда говорил,
std::mt19937
потому что это было быстро печатать и узнавать имя. Но в наши дни кажется, что все говорят, что Mersenne Twister очень тяжелый и кеша и даже не проходит все статистические тесты, которые делают другие.Я хотел бы сказать,
std::default_random_engine
потому что это очевидный «дефолт». Но я не знаю, меняется ли он от платформы к платформе, и я не знаю, статистически ли это хорошо.Поскольку в наши дни все работают на 64-битной платформе, следует ли нам хотя бы использовать
std::mt19937_64
overstd::mt19937
?Я хотел бы сказать,
pcg64
илиxoroshiro128
потому что они кажутся уважаемыми и легкими, но они вообще не существуют<random>
.Я ничего не знаю
minstd_rand
,minstd_rand0
,ranlux24
,knuth_b
конечно , они должны быть хорошо для чего - то - и т.д.?
Очевидно, здесь есть некоторые конкурирующие ограничения.
Сила двигателя. (
<random>
не имеет криптографически сильных PRNG, но все же некоторые из стандартизированных «слабее» других, верно?)sizeof
двигатель.Скорость его
operator()
.Легкость высева.
mt19937
общеизвестно, что правильно посеять правильно, потому что у него так много состояний для инициализации.Переносимость между поставщиками библиотек. Если один поставщик
foo_engine
производит разные номера от другогоfoo_engine
, это не подходит для некоторых приложений. (Надеюсь, это не исключает ничего, кроме, может бытьdefault_random_engine
.)
Взвесив все эти ограничения как можно лучше, что бы вы назвали окончательным ответом «наилучшая практика - оставаться в пределах стандартной библиотеки»? Должен ли я просто продолжать использовать std::mt19937
, или как?
Ответы:
Справочник C ++ перечисляет все случайные механизмы, в настоящее время предоставляемые C ++. Тем не менее, выбор двигателей оставляет желать лучшего (например, см. Мой список высококачественных генераторов случайных чисел ). Например:
default_random_engine
определяется реализацией, поэтому неизвестно, есть ли у движка статистические недостатки, о которых может заботиться приложение.linear_congruential_engine
реализует линейные конгруэнтные генераторы. Однако они имеют тенденцию иметь низкое качество, если модуль не является простым и очень большим (не менее 64 бит). Кроме того, они не могут допустить больше семян, чем их модуль.minstd_rand0
иminstd_rand
допускают только около 2 ^ 31 семян.knuth_b
оборачиваетminstd_rand0
и делает перемешивание Бэйса-Дарема.mt19937
иmt19937_64
может допускать намного большеstd::seed_seq
начальных значенийrandom_device
, если их лучше инициализировать (например, путем инициализации с несколькими выходами , а не только с одним), но они используют около 2500 байтов состояния.ranlux24
иranlux48
использовать около 577 бит состояния, но они медленные (они работают, сохраняя одни и отбрасывая другие псевдослучайные выходные данные).Однако в C ++ также есть два движка, которые обертывают другой движок, чтобы потенциально улучшить его свойства случайности:
discard_block_engine
отбрасывает некоторые из выходов данного случайного двигателя.shuffle_order_engine
реализует перемешивание Бэйса – Дарема для данного случайного движка.Например, можно, например, иметь Отсеки-Durham перетасовка
mt19937
,ranlux24
или обычаяlinear_congruential_engine
сshuffle_order_engine
. Возможно, завернутый двигатель лучше по качеству, чем оригинальный. Однако трудно предсказать статистическое качество нового движка без его тестирования .Таким образом, в ожидании таких тестов кажется, что
mt19937
это самый практичный движок в стандарте C ++ на данный момент. Однако мне известно, по крайней мере, одно предложение добавить еще один механизм случайных чисел в будущие версии C ++ (см. Документ C ++ P2075 ).источник
По ссылке C ++ ,
default_random_engine
:Таким образом , для легкого использования вы не должны беспокоиться о чем - либо, семена
default_random_engine
с ,Epoch Time (time(0))
и что было бы хорошо достаточно;)источник