Favolas
Favolas

Reputation: 7243

Java normal distribution with mean diff than zero and std deviance different than one

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

Code

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.

  1. What does second does? It's some kind of protection?
  2. How does this code uses the normal distribution? Can't seem to figure it out...

Upvotes: 1

Views: 2080

Answers (1)

Ted Hopp
Ted Hopp

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

Related Questions