The C library function rand() has been around for decades, yet it still has several serious limitations which prevent it from being a viable choice for new code.
The range that rand() will produce numbers in is usually not as large as the majority of programmers assume it is. On a large number of platforms, RAND_MAX is only 32767. This means that rand() % 100000 cannot produce a uniform range: some values will occur more often than others, and the higher range is inaccessible.
A common attempt to find a number in a restricted range:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
// Call this function with the provided arguments
std::srand(static_cast<unsigned>(std::time(nullptr)));
std::cout << std::rand() % 6 + 1 << '\n';
}
This will seed the random number generator with the current time. The number rand() % 6 + 1 will attempt to produce a number between 1 and 6. However, the low bits of many older generators are not particularly random, and so the numbers generated will not be uniform. Even if two runs occur within the same second, they will produce the same sequence because they are seeded with the same number.
This seed problem will occur even if you are not using a modulo operation to restrict range.
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
// Perform this conversion explicitly
std::srand(static_cast<unsigned>(std::time(nullptr)));
std::cout << std::rand() << '\n';
std::cout << std::rand() << '\n';
}
In this case, both numbers are selected from the random number sequence after it is seeded with the current time, meaning that for any two programs run within the same second, they will produce the same pairs of numbers. The time function does not provide sufficiently varied entropy to make it suitable for seeding random number generators.
rand() is not required to be thread safe. Any call to it from one thread at the same time as another thread calls it can result in corruption of the random number state and undefined behavior, even to the extent of repeated or predictable random numbers being produced. Modern generators in <random> solve this problem by encapsulating their state within separate objects.
Finally, the quality of the random number generation used behind the rand() function is not very high. Short periods and statistically flawed, detectable sequences are not uncommon; std::mt19937 was designed specifically to eliminate this type of problem, and should be the one you are using.
All of the problems mentioned above are resolved when you start using a modern engine and distributions. The older rand() interface should still be kept in C++ for compatibility, however, the issues of range limitation, biased remainder arithmetic, low seed variability, non thread safety, and statistically poor distribution all make it unsuitable for most new programs.
0 comments
No comments yet. Be the first.