Why do you hate me rand()?!

TL;DR – I’ve always heard rand() sucked for generating (cryptographically strong) random numbers, but it turns out it’s just kind of bad in general too LOL.

OK so this is bizarre, I made a default settings console project in MSVC 2012 with the code below:

#include 
#include 
#include 

int main(int argc, char** argv)
{
	time_t thetime = 0;
	time(&thetime);
	srand(thetime);
	int a = rand();
	int b = rand();
	int c = rand();
	int d = rand();

	printf("time = %llu (%llu)rna = %irnb = %irnc =t %irnd = %irn", thetime, thetime % RAND_MAX, a, b, c, d);
	return 0;
}

Here are some sample outputs, can you see what’s wrong?!

time = 1371620230 (26377)
a = 11108
b = 28489
c = 18911
d = 15679
time = 1371620268 (26415)
a = 11232
b = 10944
c = 9621
d = 12581
time = 1371620289 (26436)
a = 11301
b = 7285
c = 24321
d = 26390
time = 1371620310 (26457)
a = 11369
b = 3625
c = 6252
d = 7432
time = 1371620332 (26479)
a = 11441
b = 10714
c = 6048
d = 12537

5 times in a row you can see that the first number randomly generated is in the 11,000’s. You can also see that it’s steadily increasing.

I included the time modulo RAND_MAX in case that was the first number returned but it isn’t. I also looked at the numbers in hex and there isn’t a clear pattern there either. I can’t really discern the correlation between the time and the first random number, but there is definitely a pattern of some kind.

You always hear you shouldn’t use rand() if you need really high quality random numbers (like used for encryption), but i always figured if you use srand() with time, your number will be good enough for games at least. Turns out, you might want to throw out the first random number rand gives you before using the stuff for your games too. Maybe throw out a couple just in case! 😛

You might wonder why b,c,d are seemingly more random then a, but that’s likely due to the Avalanche Effect aka “sensitivity to initial conditions” which as it turns out is a nice property of cryptographic algorithms as well as pseudo random number generators. That is also a fundamental idea from Chaos Theory.

Essentially, as you ask for more random numbers, they ought to be more unpredictable, and more “random”. You just get some trash in the beginning.

Anyways… I’m super surprised by just how bad rand() is… I guess I never looked at it like this before (or maybe this is some new bad behavior in MSVC 2012?). Also, RAND_MAX is defined for me as 0x7fff. Ouchies, where are the rest of our numbers? 😛


4 comments

  1. The reason why your random numbers are seemingly less random is because the number of seconds since Jan 1st, 1970 is a tad deterministic. The formula that rand uses weights the higher bits more importantly than the lower bits (multiplication by the seed and some prime numbers and then shifting the bits down). If you use a better random seed you should see better random results.

    Like

  2. Fair enough, I’m just surprised srand/rand doesn’t do a better job with the seed. Maybe there’s a good reason for it though…

    I guess if we really cared that much we could hash what time returns before passing it in to srand? hehe

    Like

    • To be fair to the algorithm you’re changing 3 decimal digits in the seed and then complaining that you’re only seeing three decimal digits variation in the first output. Hashing it with a constant wouldn’t change the behaviour. Though you could try pulling in other random-ish values like process ID or tick count though none of these are good enough for cryptography they’re good enough for your needs.

      Or you could do the classic of priming the pump by calling rand a few times before actually using it’s results.

      Like

  3. Good hashes have the property that small changes in the input make large changes in the output, so hashing the time and passing that to srand seems like it ought to be a decent fix.

    Like


Leave a comment