Usage of rand()
is usually frowned upon despite using a seed via srand()
. Why would that be the case? What better alternatives are available?
There are two parts to this story.
First, rand
is a pseudorandom number generator. This means it depends on a seed. For a given seed it will always give the same sequence (assuming the same implementation). This makes it not suitable for certain applications where security is of a great concern. But this is not specific to rand
. It's an issue with any pseudo-random generator. And there are most certainly a lot of classes of problems where a pseudo-random generator is acceptable. A true random generator has its own issues (efficiency, implementation, entropy) so for problems that are not security related most often a pseudo-random generator is used.
So you analyzed your problem and you conclude a pseudo-random generator is the solution. And here we arrive to the real troubles with the C random library (which includes rand
and srand
) that are specific to it and make it obsolete (a.k.a.: the reasons you should never use rand
and the C random library).
One issue is that it has a global state (set by srand
). This makes it impossible to use multiple random engines at the same time. It also greatly complicates multithreaded tasks.
The most visible problem of it is that it lacks a distribution engine: rand
gives you a number in interval [0 RAND_MAX]
. It is uniform in this interval, which means that each number in this interval has the same probability to appear. But most often you need a random number in a specific interval. Let's say [0, 1017]
. A commonly (and naive) used formula is rand() % 1018
. But the issue with this is that unless RAND_MAX
is an exact multiple of 1018
you won't get an uniform distribution.
Another issue is the Quality of Implementation of rand
. There are other answers here detailing this better than I could, so please read them.
In modern C++ you should definitely use the C++ library from <random>
which comes with multiple random well-defined engines and various distributions for integer and floating point types.
None of the answers here explains the real reason of being rand()
bad.
rand()
is a pseudo-random number generator (PRNG), but this doesn't mean it must be bad. Actually, there are very good PRNGs, which are statistically hard or impossible to distinguish from true random numbers.
rand()
is completely implementation defined, but historically it is implemented as a Linear Congruential Generator (LCG), which is usually a fast, but notoriously bad class of PRNGs. The lower bits of these generators have much lower statistical randomness than the higher bits and the generated numbers can produce visible lattice and/or planar structures (the best example of that is the famous RANDU PRNG). Some implementations try to reduce the lower bits problem by shifting the bits right by a pre-defined amount, however this kind of solution also reduces the range of the output.
Still, there are notable examples of excellent LCGs, like L'Ecuyer's 64 and 128 bits multiplicative linear congruential generators presented in Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure, Pierre L'Ecuyer, 1999.
The general rule of thumb is that don't trust rand()
, use your own pseudo-random number generator which fits your needs and usage requirements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With