The problem appears to be that your system's rand()
implementation is sensitive to the fact that successive return values from time()
don't differ by much — that is, aren't supplying much entropy.
I tried your code on my machine and got remarkably similar results.
You need to provide a bit more entropy, to "mix things up".
One technique I like to use (at least, on Unix-like systems) is to add the process ID into the seed, since the pid will be different each time. Usually I've done it like this:
srand(time(NULL) + getpid());
This is a good way to make sure your program generates different results even if you invoke it twice in the same second.
Unfortunately, this wasn't enough to make a difference with your code on my machine, and I suspect it won't help on yours, either. The problem is that (especially on a non-loaded system) the process ID typically just increments by 1 or 2 each time also, and it's adding in to the same low-order bits of time
's return value which also aren't changing by much. (And the high order bits of the pid don't change at all, and are being added to the high-order bits of the time of day, which also aren't changing.)
On my system, I got decent results with
srand(time(NULL) ^ (getpid() << 16));
and I suggest you try this.
If that doesn't help, you'll want to use either a significantly better entropy source, or a significantly better pseudorandom number generator.
These days, virtually all Unix-like systems have a good source of entropy accessible via the special file /dev/random
. So a superior way of seeding a pseudorandom number generator is with code like this:
FILE *fp = fopen("/dev/random", "rb");
if(fp != NULL) {
unsigned int seed;
fread(&seed, sizeof(seed), 1, fp);
srand(seed);
fclose(fp);
}
(For a production program, obviously you'd have to decide what to do if the fopen
call failed.)
Eric Postpischil's answer mentions random
, a significantly better PRNG available on most systems.