Mersenne Twister — это pRNG (генератор псевдослучайных чисел), основанный на регистре сдвига, и, следовательно, он подвержен неправильным начальным числам с длинными сериями нулей или единиц, которые приводят к относительно предсказуемым результатам до тех пор, пока внутреннее состояние не будет достаточно перепутано.
Однако конструктор, который принимает одно значение, использует сложную функцию для этого начального значения, которая предназначена для минимизации вероятности создания таких «плохих» состояний. Существует второй способ инициализации mt19937
, когда вы напрямую устанавливаете внутреннее состояние через объект, соответствующий концепции SeedSequence. Это второй метод инициализации, когда вам, возможно, придется побеспокоиться о выборе «хорошего» состояния или о прогреве.
Стандарт включает объект, соответствующий концепции SeedSequence, который называется seed_seq
. seed_seq
принимает произвольное количество входных начальных значений, а затем выполняет определенные операции над этими значениями, чтобы создать последовательность различных значений, подходящих для прямой установки внутреннего состояния pRNG.
Вот пример загрузки исходной последовательности с достаточным количеством случайных данных, чтобы заполнить все состояние std::mt19937
:
std::array<int, 624> seed_data;
std::random_device r;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 eng(seq);
Это гарантирует рандомизацию всего состояния. Кроме того, каждый движок указывает, сколько данных он считывает из seed_sequence, поэтому вы можете прочитать документацию, чтобы найти эту информацию для любого движка, который вы используете.
Хотя здесь я загружаю seed_seq полностью из std::random_device
, seed_seq
указано так, что всего несколько чисел, которые не являются особенно случайными, должны работать хорошо. Например:
std::seed_seq seq{1, 2, 3, 4, 5};
std::mt19937 eng(seq);
В комментариях ниже Cubbi указывает, что seed_seq
работает, выполняя для вас последовательность разогрева.
Вот что должно быть вашим «по умолчанию» для раздачи:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 rng(seed);
person
bames53
schedule
19.03.2013
std::random_device
, так как он может бросить в любой момент по разным бессмысленным причинам. Вы можете обернуть его в блок try..catch, но я бы рекомендовал использовать специфичный для платформы способ получения случайного числа: в Windows используйте Crypto API, в противном случае используйте/dev/urandom/
. - person BoltzmannBrain   schedule 06.12.2018