Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I properly seed C++11 std::default_random_engine?

Tags:

c++

random

c++11

According to this post, intuitive seeding with std::random_device may not produce the expected results. In particular, if the Mersenne Twister engine is used, not all the initialization states can be reached. Using seed_seq doesn't helper either, since it is not a bijection.

This all, as far as I understand, means that not the std::uniform_int_distribution will not really be uniform - because not all seed values are possible.

I'd like to simply generate a couple of random numbers. While this is a really interesting topic which I will certainly devote some of my free time, many people may not have this possibility.

So the question is: how should I properly seed the std::default_random_engine so that it simply does what I expect?

like image 638
marmistrz Avatar asked May 17 '17 17:05

marmistrz


Video Answer


1 Answers

A uniform_int_distribution will still be uniform however you seed it. But better seeding can reduce chances of getting the same sequence of uniformly distributed values.

I think for most purposes using a std::seed_seq with about 8 random 32bit ints from std::random_device should be sufficient. It is not perfect, for the reasons given in the post you linked but if you need really secure numbers for cryptographic purposes you shouldn't really be using a pseudo random number generator anyway:

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 };
}
like image 193
Chris Drew Avatar answered Sep 20 '22 08:09

Chris Drew