user5667679
user5667679

Reputation: 35

generate random number in c++

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

Answers (2)

user1118321
user1118321

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

ZisIsNotZis
ZisIsNotZis

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

Related Questions