top | item 44405076

(no title)

nynx | 8 months ago

Is it possible to initialize a prng in C++’s std correctly?

discuss

order

sltkr|8 months ago

My standard code for doing this looks like this:

    #include <algorithm>
    #include <array>
    #include <random>
    
    std::mt19937 InitializeRng() {
      std::array<unsigned int, 624> seed_data;
      std::random_device dev;
      std::generate_n(seed_data.data(), seed_data.size(), std::ref(dev));
      std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
      return std::mt19937(seq);
    }
This generates seed_seq with 19968 bits of random data, which is enough for the 19937 bits of Mersenne Twister internal state.

Note that 19668 bits of random data is overkill; something like 256 or 128 bits would probably enough for practical purposes. But I believe there is no real need to limit the amount of data extracted from a random source. Modern operating systems are pretty good at generating large amounts of random data quickly. But if this is a concern, just change 624 to 4/8/16/32 for 128/256/512/1024 bits of entropy. In practice, I don't think you'll notice a difference either in randomness or initialization speed.

edit: also, if performance is a concern, consider changing mt19937 to mt19937_64, which is the 64-bit variant of mt19937 that is incompatible (generates different numbers) but is almost twice as fast on 64-bit platforms (i.e. most platforms today).

loeg|8 months ago

If you're aware/concerned about seeding, you probably aren't using the C++ std prng (mt19937) anyway -- other prngs have desirable properties like vastly smaller state, better performance, or cryptographic security.

on_the_train|8 months ago

No one uses the <random> header as it's cursed and the usual cult of backwards compatibility ensures it'll stay that way.

There are several high quality alternatives that people use.

nynx|8 months ago

How did it get into the standard then?

thechao|8 months ago

I've found it easier to write my own PRNG than to use the std. Using the std PRNG is about as buggy as my implementation, so the trade-off is reasonable. I usually need non-cryptographically strong PRNGs, so xorshift128+ is sufficient.

loeg|8 months ago

Sadly, people that don't know better use std::mt19937 all the time :-(.