From this question: Random number generator which gravitates numbers to any given number in range? I did some research since I\'ve come across such a random number generator
Your code is fine. Your mistake is thinking that it should return values exclusively within [0, 1]
. The (standard) normal distribution is a distribution with nonzero weight on the entire real line. That is, values outside of [0, 1]
are possible. In fact, values within [-1, 0]
are just as likely as values within [0, 1]
, and moreover, the complement of [0, 1]
has about 66% of the weight of the normal distribution. Therefore, 66% of the time we expect a value outside of [0, 1]
.
Also, I think this is not the Box-Mueller transform, but is actually the Marsaglia polar method.
The uniform random variate is indeed within 0..1, but the gaussian random variate (which is what Box-Muller algorithm generates) can be anywhere on the real line. See wiki/NormalDistribution for details.
I think the function returns polar coordinates. So you need both values to get correct results.
Also, Gaussian distribution is not between 0 .. 1
. It can easily end up as 1000, but probability of such occurrence is extremely low.
I am no mathematician, or statistician, but if I think about this I would not expect a Gaussian distribution to return numbers in an exact range. Given your implementation the mean is 0 and the standard deviation is 1 so I would expect values distributed on the bell curve with 0 at the center and then reducing as the numbers deviate from 0 on either side. So the sequence would definitely cover both +/- numbers.
Then since it is statistical, why would it be hard limited to -1..1 just because the std.dev is 1? There can statistically be some play on either side and still fulfill the statistical requirement.
This is a monte carlo method so you can't clamp the result, but what you can do is ignore samples.
// return random value in the range [0,1].
double gaussian_random()
{
double sigma = 1.0/8.0; // or whatever works.
while ( 1 ) {
double z = gaussian() * sigma + 0.5;
if (z >= 0.0 && z <= 1.0)
return z;
}
}