
Randoms
It seems like lots of people around here have problems with random numbers. I thought this might help understand the beast. It helped me.
I used this simple program to do a little study.
Code:
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
time_t now = time(&now);
srand((unsigned int)now);
ofstream randout(argv[1]);
int randnum;
for(int x = 20;x>0;x)
{
randnum = rand()%6+1;
cout<<randnum<<endl;
randout<<randnum<<endl;
}
randout.close();
system("pause");
return 0;
}
You give the program a text file name on the command line, and it stores the 20 random values in the text file, overwriting whatever was there. The numbers are from 1 to 6 (like a die).
I executed this ten times and came out with data like this.
You would expect, if the numbers are truly random, that as you get more and more results to get roughly the same number of all the possible values, which would give you an average value of 3.5 ((123456)/6 = 3.5). These averages range from 3.05 to 3.75. As you can see, the overall average is 3.44, which I suppose is close enough to 3.5.
That's it, this method works very well for generating random values.

The delay in between rand() is irrelevant. In almost every single PRNG, the next random number is generated by multiplication of the previous random with a constant, followed by addition.
You see rand() often gives the same numbers in a row because the lowest bits aren't usually as random as the upper bits.

Not sure I understand your explanation, but you seem to know more about it than I do. I went back through and tried with and without the pause, and I believe you're right. I was certain I remembered a big difference with and without. Oh well.
Sample results produced without the pause:
61142516615233125414
Sample results produced with the pause:
63525455311142542213
At any rate, I'll be editing my original post so not to confuse anybody.


As Cat noted, linearcongruential PRNGs (which most rand() implementations are) have 'bad' loworder bits. To get around this, and generate numbers in the range [low, high], the following is often much better (more 'random') because the reliance is on highorder bits:
int randnum = low + int(double(high  low) * rand() / (RAND_MAX + 1.0));
A linearcongruential PRNG works as follows:
x[i+1] = (a*x[i]+c) % m
for constants a, c, m. (Note, the above equation is often not a good way to implement it due to potential overflow errors.)

>int randnum = low + int(double(high  low) * rand() / (RAND_MAX + 1.0));
int randnum = low + int(double(high  low) * rand() / RAND_MAX);
Leave off that plus one at the end though. Right Zach?

Indeed.
Thats what I get for copynpasting without paying attention. :rolleyes:
Thanks :)