Как я должен правильно семя С++ 11 std:: default_random_engine?

В соответствии с этот пост, интуитивно понятный посев с std::random_device может не дать ожидаемых результатов. В частности, если используется двигатель Mersenne Twister, могут быть достигнуты не все состояния инициализации. Использование seed_seq также не помогает, так как это не биекция.

Это все, насколько я понимаю, означает, что не std::uniform_int_distribution не будет действительно однородным, потому что не все значения семян возможны.

Я хотел бы просто создать пару случайных чисел. Хотя это действительно интересная тема, которую я, безусловно, посвящу часть своего свободного времени, многие люди могут не иметь такой возможности.

Итак, вопрос в том, как правильно семенить std::default_random_engine, чтобы он просто выполнял то, что я ожидаю?

Ответ 1

A uniform_int_distribution будет по-прежнему однородным, но вы его засеваете. Но лучший посев может уменьшить вероятность получения одинаковой последовательности равномерно распределенных значений.

Я думаю, что для большинства целей использование std::seed_seq с примерно 8 случайными 32-битными ints из std::random_device должно быть достаточным. Это не идеально, по причинам, указанным в сообщении, которое вы связали, но если вам нужны действительно защищенные номера для криптографических целей, вы вообще не должны использовать генератор псевдослучайных чисел:

constexpr std::size_t SEED_LENGTH = 8;

std::array<uint_fast32_t, SEED_LENGTH> generateSeedData() {
  std::array<uint_fast32_t, SEED_LENGTH> random_data;
  std::random_device random_source;
  std::generate(random_data.begin(), random_data.end(), std::ref(random_source));
  return random_data;
}

std::mt19937 createEngine() {
  auto random_data = generateSeedData();
  std::seed_seq seed_seq(random_data.begin(), random_data.end());
  return std::mt19937{ seed_seq };
}