Reputation: 35
I get a task to generate tens of thousands random number in c++. I've googled a lot about random number in c++ and look up the c++ reference, but I got confused now.
As I know, random_device is a non-deterministic random number generator, but every time I re-run my program, the random number generated by random_device is the same. So how do I set a seed for random_device to make the random number is different when I restart my program?
And I've read that "std::random_device could run out of entropy if you try to get a lot of numbers from it. That could cause it to block until you move the mouse or something". That means my program could pause at some time. How can I avoid this happening?
Upvotes: 2
Views: 1894
Reputation: 26345
Assuming you don't need cryptographically secure random number generation, then you can use the std::mt19937
random generator. It's the Meresenne Twister random generator that has a period of 219937 iterations before it repeats. I've used it like this in the past:
std::array<int, std::mt19937::state_size> seedData;
std::random_device randDevice;
std::mt19937 eng;
std::uniform_real_distribution<double> randGen(0, 1);
std::generate_n(seedData.data(), seedData.size(), std::ref(randDevice));
std::seed_seq seq(std::begin(seedData), std::end(seedData));
eng.seed(seq);
That creates an array containing the seed of the appropriate size. It creates a random device to set up the seed. Then it creates an mt19937
random generator engine to generate the numbers. To use it to generate values between 0 and 1 you can use the std::uniform_real_distribution
like this:
double randVal = randGen(eng);
Upvotes: 1
Reputation: 1740
From here, you can see std::random_device
does not always guarantee to be non-deterministic:
std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.
On Linux, it by default uses /dev/urandom
or RDRND
CPU instruction according to here:
The implementations in libc++ and libstdc++ expect token to be the name of a character device that produces random numbers when read from, with the default value "/dev/urandom", although where the CPU instruction RDRND is available, libstdc++ uses that as the default.
which won't block. You can switch to a even secured device /dev/random
using approach here, but that device will block if not having enough entropy.
On Windows, I'm not sure about such device therefore it might fall back to some PRNG which requires some kind of seed.
To solve the problem cross-platformly, as @Binara mentioned, you can use std::rand
from <cstdlib>
. This function will not block, and you can use std::srand(somethingLikeCurrentTime)
to make it some-what non-deterministic.
As @user1118321 mentioned, if you want to use a more secured PRNG, you might consider std::mersenne_twister_engine
and use std::random_device
to generate a seed of it. This approach is suggested here.
Upvotes: 1