Reputation: 7243
My professor is simulating the arrival of clients to a bank. It says that clients arrive following a normal distribution with 3.5 mean and 1.3 std deviance.
The problem is that I'm with some difficulties understanding why is using this code. I believe that the code he provided is receiving a stream, mean and std to generate a random number
public class Random {
private static double second=0;
static double normal(int stream, double mean, double std){
double v1=0, v2=0, y1, y2, x1, x2, w=2;
if (second!=0 ){
return second;
}
while(w>1){
v1=2*RandomGenerator.rand(stream)-1;
v2=2*RandomGenerator.rand(stream)-1;
w=Math.pow(v1,2)+Math.pow(v2,2);
}
y1=v1*Math.pow((-2*Math.log(w))/w, 0.5);
y2=v2*Math.pow((-2*Math.log(w))/w, 0.5);
x1=mean+y1*std;
x2=mean+y2*std;
second=x2;
return x1;
}
}
My math lessons were many years ago so it's a bit hard to understand this normal distribution and after searched the internet to how calculate normal distribution I couldn't find any formula resembling to the code given.
So, these are my questions.
second
does? It's some kind of protection?Upvotes: 1
Views: 2080
Reputation: 234795
I'll answer the questions in reverse order. The central part of the method is a standard technique for converting two random variables drawn from a uniform distribution on [0, 1] into two random variables drawn from a normal distribution with a given mean and standard deviation. (It's called the Box-Muller transform.) The while
loop uses a generate-and-test technique to generate a random point (v1, v2) from a 2-D uniform distribution on the unit circle. The mapping from (v1, v2) to (y1, y2) converts the uniform distribution to a 2-D normal distribution with zero mean and unit standard deviation. This is then shifted and scaled to get (x1, x2) with the desired mean and standard deviation.
With a method of generating pairs of normally distributed variables now in hand, the rest of the code works as follows: if second == 0
, this is a signal that new values need to be generated, so it falls through the if
and generates a pair of values. It then saves one of the values in second
and returns the other. The next time the method is called, it notices that there's a valid value in second
and returns that immediately, instead of generating more values.
There's a major bug in the code: second
should be reset to zero before it's value is returned; otherwise it will always continue returning the second random value (which won't seem so random after the second call). Even if that flaw were corrected, there's a second problem. Every other returned value will have zero probability of having value 0. Theoretically this isn't too bad because the probability of a normally distributed random sample having value exactly zero is...zero! However, it is still a flaw.
I'd rewrite the code as follows:
public class Random {
private static double second;
private static boolean secondValid = false;
static double normal(int stream, double mean, double std) {
double v1, v2, y1, y2, x1, x2, w;
if (secondValid) {
secondValid = false;
return second;
}
do {
v1 = 2 * RandomGenerator.rand(stream) - 1;
v2 = 2 * RandomGenerator.rand(stream) - 1;
w = v1 * v1 + v2 * v2;
} while (w > 1);
y1 = v1 * Math.sqrt(-2 * Math.log(w) / w);
y2 = v2 * Math.sqrt(-2 * Math.log(w) / w);
x1 = mean + y1 * std;
x2 = mean + y2 * std;
second = x2;
secondValid = true;
return x1;
}
}
Upvotes: 2