Why does rand() yield the same sequence of numbers on every run?
Every time I run a program with rand()
it gives me the same results.
Example:
#include <iostream>
#include <cstdlib>
using namespace std;
int random (int low, int high) {
if (low > high)
return high;
return low + (rand() % (high - low + 1));
}
int main (int argc, char* argv []) {
for (int i = 0; i < 5; i++)
cout << random (2, 5) << endl;
}
Output:
3
5
4
2
3
Each time I run the program it outputs the same numbers every time. Is there a way around this?
Solution 1:
The seed for the random number generator is not set.
If you call srand((unsigned int)time(NULL))
then you will get more random results:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand((unsigned int)time(NULL));
cout << rand() << endl;
return 0;
}
The reason is that a random number generated from the rand()
function isn't actually random. It simply is a transformation. Wikipedia gives a better explanation of the meaning of pseudorandom number generator: deterministic random bit generator. Every time you call rand()
it takes the seed and/or the last random number(s) generated (the C standard doesn't specify the algorithm used, though C++11 has facilities for specifying some popular algorithms), runs a mathematical operation on those numbers, and returns the result. So if the seed state is the same each time (as it is if you don't call srand
with a truly random number), then you will always get the same 'random' numbers out.
If you want to know more, you can read the following:
http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/
http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/
Solution 2:
If you call rand()
without first calling srand()
, it will act as if you have called srand(1)
implicitly. The relevant bit of the standard C99 7.20.2.2 The srand function
(on which cstdlib
is based) states:
If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
In other words, you will get the same sequence each time. You can change your main
into:
int main (int argc, char* argv []) {
srand (time (0)); // needs ctime header.
for (int i = 0; i < 5; i++)
cout << random (2, 5) << endl;
wait ();
}
to fix this, assuming you don't run it more than once a second.
As mentioned, you'll need the ctime
header for this. You should also be pulling in cstdlib
since that's where rand
and srand
live. It's also usually a good idea to use the cXXX
headers rather than the XXX.h
ones (cmath
rather than math.h
, for example).
So, having made all those changes (and using explicit namespaces, which I prefer though others may not), I'd end up with:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
void wait () {
int e;
std::cin >> e;
}
int random (int low, int high) {
if (low > high) return high;
return low + (std::rand() % (high - low + 1));
}
int main (int argc, char* argv []) {
std::srand (std::time (0));
for (int i = 0; i < 5; i++)
std::cout << random (2, 5) << '\n';
wait ();
}
which gives a different sequence each time I run it, for a few times anyway. Obviously, there's a hard limit on when the data will repeat (there are only 45 possibilities) and the "random" nature of the output means it may repeat before then as well :-)
Solution 3:
That's a feature of the rand()
function.
What you have is not a random number generator, but more strictly a "pseudorandom number generator". Being able to reproduce the same random sequences for the same seed (you seed using the srand(x)
function) can be important to reproduce bugs or to preserve state across program runs.
Personally, I use this feature to be able to pause/persist rendering-processes in a Monte Carlo-based terrain renderer. A nice side effect is that you are able to guarantee different Monte Carlo experiments on different machines, and therefore be able to generate guaranteed different results that can then be reduced in a final step to a higher quality end result (of course you can later reuse this higher quality end result to produce even higher quality results).
Note, however, that neither C nor C++ define the number sequence from rand()
. So if you need guaranteed sequences across platforms, use one of C++11's new random number generators (e.g. a Mersenne Twister), roll your own (some generators are almost trivial to grasp, however, because most of them rely on specific overflow behaviour their implementation might not be trivial), or use a third-party component (e.g. boost::random).