I need a 'good' way to initialize the pseudo-random number generator in C++. I've found an article that states:
In order to generate random-like numbers, srand is usually initialized to some distinctive value, like those related with the execution time. For example, the value returned by the function time (declared in header ctime) is different each second, which is distinctive enough for most randoming needs.
Unixtime isn't distinctive enough for my application. What's a better way to initialize this? Bonus points if it's portable, but the code will primarily be running on Linux hosts.
I was thinking of doing some pid/unixtime math to get an int, or possibly reading data from /dev/urandom
.
Thanks!
EDIT
Yes, I am actually starting my application multiple times a second and I've run into collisions.
if you need a better random number generator, don't use the libc rand. Instead just use something like
/dev/random
or/dev/urandom
directly (read in anint
directly from it or something like that).The only real benefit of the libc rand is that given a seed, it is predictable which helps with debugging.
The real question you must ask yourself is what randomness quality you need.
libc random is a LCG
The quality of randomness will be low whatever input you provide srand with.
If you simply need to make sure that different instances will have different initializations, you can mix process id (getpid), thread id and a timer. Mix the results with xor. Entropy should be sufficient for most applications.
Example :
For better random quality, use /dev/urandom. You can make the above code portable in using boost::thread and boost::date_time.
This is what I've used for small command line programs that can be run frequently (multiple times a second):
Where mix is:
The
c++11
version of the top voted post by Jonathan Wright:C++11
random_device
If you need reasonable quality then you should not be using rand() in the first place; you should use the
<random>
library. It provides lots of great functionality like a variety of engines for different quality/size/performance trade-offs, re-entrancy, and pre-defined distributions so you don't end up getting them wrong. It may even provide easy access to non-deterministic random data, (e.g., /dev/random), depending on your implementation.eng
is a source of randomness, here a built-in implementation of mersenne twister. We seed it using random_device, which in any decent implementation will be a non-determanistic RNG, and seed_seq to combine more than 32-bits of random data. For example in libc++ random_device accesses /dev/urandom by default (though you can give it another file to access instead).Next we create a distribution such that, given a source of randomness, repeated calls to the distribution will produce a uniform distribution of ints from 1 to 100. Then we proceed to using the distribution repeatedly and printing the results.
tv.tv_usec is in microseconds. This should be acceptable seed.