C rand() slightly biased

Viewed 166

I'm using the rand() function from the Standard c Library to generate numbers for a Monte Carlo simulation in the range 0 to 1 using:

(double)rand()/RAND_MAX

But I noticed that the result was slightly off. I checked at which value the generated numbers averaged out and it was slightly under the expected 0.5.

I read that rand() is Modulo biased but I’m not using modulo here. Is there a more precise way to generate numbers between 1 and 0?

Edit: I'm fairly new to Prngs so i didn't know that some prngs arent threadsafe. I should have mentioned that i used rand() multithreaded. Regardless, your answers helped me to find a faster and threadsafe rng.

3 Answers

It depends on your C implementation. Some have a higher quality implementation of rand than others. Maybe use arc4random, or some other crypto based PRNG instead.

My personal favourite is xoroshiro. It passes most pseudorandomness tests and it's incredibly fast, much faster than rand().

Of course, in the typical case rand() is a notoriously poor PRNG. (On my system, man rand prints "rand, rand_r, srand, sranddev -- bad random number generator".)

rand tends to be fine for some things, but I think it's pretty widely agreed that it's never good enough for decent Monte Carol simulation. Quite aside from its distribution, its period tends not to be long enough. (Typical implementations keep ~32 bits of state, so they start repeating after 4.3 billion samples.)

With that said, (double)rand()/RAND_MAX is averaging out at 0.5 for me on my machine -- to be precise, I got 0.500004 after 1,000,000,000 samples. I suspect your system's implementation may be broken -- one possibility that pops to mind is that it is wrongly emitting numbers in the range from 0 to RAND_MAX-1. You might try averaging rand()/(RAND_MAX-1.) and see what happens.

(ObIdleOpinionating: I wish systems would implement rand() better, instead of telling you not to use it and giving you a better PRNG under a different, nonstandard name. But it doesn't matter what I wish, because implementing a crappy rand() alongside a better-but-nonstandard alternatively-named version is what everybody seems to do.)

Related