I'm getting strange behavior out of the rand()
function in C. The result of the first call to rand()
after srand()
looks very predictable and un-random. I tried both with the seed from 0 to 10, and using the system time as a seed and sleeping 1 sec after each call to srand, produced similar results: the output is almost a linear function of the seed.
EDIT: I changed my test program so that the first call to rand after calling srand, determines how many times rand is called to generate the result. Following is first the original program with seed 0-10 and its output; then, the modified program with seed 0-10 and its output.
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
unsigned int randnum, ind;
char line[130];
for (ind=0; ind <=10; ind++) {
srand(ind);
randnum = rand();
printf("%u, %u, %u, \n", ind, randnum, rand());
}
gets(line);
return 0;
}
Output:
0, 38, 7719,
1, 41, 18467,
2, 45, 29216,
3, 48, 7196,
4, 51, 17945,
5, 54, 28693,
6, 58, 6673,
7, 61, 17422,
8, 64, 28170,
9, 68, 6151,
10, 71, 16899,
The result increases by 3 or 4 when the seed is incremented by 1.
Now, the modified program and its results:
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
unsigned int randnum, nreps, ind1, ind2;
char line[130], ok;
for (ind1=0; ind1 <=25; ind1++) {
srand(ind1);
nreps = rand() % 11;
for (ind2=1; ind2 <= nreps; ind2++) rand ();
randnum = rand();
printf("%u, %u, %u \n", ind1, nreps, randnum);
}
gets(line);
return;
}
Output:
0, 5, 8365
1, 8, 24464
2, 1, 24198
3, 4, 23577
4, 7, 10960
5, 10, 28321
6, 3, 5206
7, 6, 11794
8, 9, 4670
9, 2, 22398
10, 5, 6722
11, 8, 28519
12, 0, 5628
13, 4, 30076
14, 7, 12236
15, 10, 28761
16, 2, 27002
17, 6, 15290
18, 9, 3191
19, 1, 209
20, 4, 24795
21, 8, 32575
22, 0, 14808
23, 3, 16714
24, 6, 27567
25, 10, 29202
That looks much better!
Note that OP is repeatedly calling srand()
for testing purposes.
First call to rand after calling srand doesn't look random at all
The result of the first call to
rand()
aftersrand
looks very predictable and un-random. Is this howrand()
is meant to work?
Yes, the upper bits look predictable on your machine, yet the C standard library rand()
is weakly defined. What you see is a certain possibility with a compliant compiler and library.
😉: Is 9,9,9,9,9,9 ... random?
Does the second call to
rand()
actually generate a (pseudo)random number?
Yes as did the first. Some implementations of rand()
do suffer from needing a few rand()
calls before they look random.
It is all very implementation dependent.
Using the system time as a seed and sleeping 1 sec after each call to srand, produced similar results. Is this how
rand()
is meant to function?
Yes. Once seeded, rand()
is specified to produce the same result regardless of the time elapsed between calls. If no srand()
call occurs before rand()
, rand()
acts as if srand(1)
had first occurred at program start.
Would need to see OP's true code for more detail.
Below is a common initialization.
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned seed = (unsigned) time(0);
// Maybe something to avoid same time in 2 quick program calls
seed ^= (unsigned) getpid(); // Non standard function.
srand(seed);
...
}
I had expected the first call to
rand()
aftersrand
to generate a number that isn't a simple function of the seed. But it's close to being a linear function of the seed.
Yes some srand()/rand()
routines are very simple - to the point of discouraging their use.
Thus serious random number use obliges other code.
Some srand()/rand()
implementations are better.
My GCC produced the below. Since rand()
is usually about bits, the below uses 0x%08X
to better illustrate. Also consider that RAND_MAX
may be as small as 0x7FFF
(32,767), which apparently is so in OP's case. This is another hint to OP's hobbled srand()/rand()
implementation.
RAND_MAX = 0x7FFFFFFF
0, 0x226E5331, 0x4A656E89
1, 0x6B8B4567, 0x327B23C6
2, 0x59B997FA, 0x67A3797F
3, 0x47DB4E3A, 0x1CCC40D1
4, 0x754E7DDD, 0x11265233
5, 0x232ADD1B, 0x05F2A7DD
6, 0x11560EBD, 0x7B33BFB9
7, 0x3E52DFF5, 0x6F19E243
8, 0x2D274378, 0x65114598
9, 0x1A7DD803, 0x5989B872
10, 0x486C7C6F, 0x4E32F398
Aside: gets()
is no longer, since C11, part of the C standard library. Best to not use it, even with older code.
Most implementations of rand
use a very primitive pseudo-random number algorithm called the Linear Congruential Generator (LCG) which has a strong correlation between the seed and the first number it generates. There's no rule dictating it as the standard algorithm but you'll find it's almost universal. There are plenty of better algorithms out there such as the Mersenne twister which you might be able to find in a library if this is important to you. Otherwise I'd suggest just throwing away the first couple of generated numbers, the ones you see after that will look much more random.
srand(ind);
rand();
rand();
randnum = rand();
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