Lognormal cumulative distribution function for JavaScript?

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
6 replies · 9K views
moonman239
Messages
276
Reaction score
0
Hey everyone!

I'm building a "Deal or No Deal" calculator that estimates the odds of getting a better deal than the one presented. As you can see in the title, I'm looking for a function that will calculate the CDF. For ease's sake, please only post JavaScript code (no C,Perl,BASIC,etc.)
 
Physics news on Phys.org
moonman239 said:
Hey everyone!

I'm building a "Deal or No Deal" calculator that estimates the odds of getting a better deal than the one presented. As you can see in the title, I'm looking for a function that will calculate the CDF. For ease's sake, please only post JavaScript code (no C,Perl,BASIC,etc.)

Here you go.

Assuming you have mu and sigma as parameters of the log normal distribution (see http://en.wikipedia.org/wiki/Lognormal_distribution), the algorithm is:

Code:
// Get a standard normally distributed number using Box-Muller
double z1 = Math.sqrt(-2 * Math.log(1.0 - Math.random())) 
            * Math.sin(2 * Math.PI * Math.random());

// Transform the number to the log normal distribution
double x = Math.exp(mu + sigma * z1);

Does this meet your needs?

[EDIT]Adjusted the code to prevent a domain-violation of Math.log()[/EDIT]
 
I like Serena said:
Code:
// Get a standard normally distributed number using Box-Muller
double z1 = Math.sqrt(-2 * Math.log(1.0 - Math.random())) 
            * Math.sin(2 * Math.PI * Math.random());

// Transform the number to the log normal distribution
double x = Math.exp(mu + sigma * z1);
[EDIT]Adjusted the code to prevent a domain-violation of Math.log()[/EDIT]

Uh, thanks I guess. Just to be certain you aren't missing anything, this outputs P(X <= x), correct?
EDIT: One more thing: Does the lognormal distribution seem more appropriate for my case than the normal distribution? EDIT: Pardon my asking, but do I need to run this algorithm repeatedly? EDIT: I found another one:

Code:
function rnd_bmt() {
    var x = 0, y = 0, rds, c;

    // Get two random numbers from -1 to 1.
    // If the radius is zero or greater than 1, throw them out and pick two new ones
    // Rejection sampling throws away about 20% of the pairs.
    do {
    x = Math.random()*2-1;
    y = Math.random()*2-1;
    rds = x*x + y*y;
    }
    while (rds == 0 || rds > 1)

    // This magic is the Box-Muller Transform
    c = Math.sqrt(-2*Math.log(rds)/rds);

    // It always creates a pair of numbers. I'll return them in an array.
    // This function is quite efficient so don't be afraid to throw one away if you don't need both.
    return [x*c, y*c];
}
 
Last edited:
moonman239 said:
Uh, thanks I guess. Just to be certain you aren't missing anything, this outputs P(X <= x), correct?
EDIT: One more thing: Does the lognormal distribution seem more appropriate for my case than the normal distribution? EDIT: Pardon my asking, but do I need to run this algorithm repeatedly? EDIT: I found another one: function rnd_bmt()

Oops. No sorry, this does not output P(X <= x).
It outputs a random number x in such a way that its chance matches the log-normal probability distribution.

The other algorithm you found does the same thing as my first line of code calculating z1.
That is, it generates a random number matching the standard normal distribution. It's just a bit more convoluted.

And I don't know yet what you want to use it for, so I can't tell you whether it is appropriate for your case.

To calculate P(X <= x) you'll need another algorithm.

For starters there is a version in the apache commons library you could use:
http://commons.apache.org/math/apidocs/org/apache/commons/math/distribution/NormalDistribution.html

If you call it with:
Code:
NormalDistribution.cumulativeProbability((Math.log(x) - mu) / sigma);
you'll get the P(X <= x) for the log-normal distribution.
 
Last edited by a moderator:
Here's a function for the cumulative probability and a second one for the log-normal cumulative probability

Code:
double normalCumulativeProbability(double z) 
{
    double b1 =  0.31938153; 
    double b2 = -0.356563782; 
    double b3 =  1.781477937;
    double b4 = -1.821255978;
    double b5 =  1.330274429; 
    double p  =  0.2316419; 
    double c2 =  0.3989423; 

    if (z >  6.0) { return 1.0; }; // this guards against overflow 
    if (z < -6.0) { return 0.0; };
    double a = Math.abs(z); 
    double t = 1.0/(1.0+a*p); 
    double b = c2*Math.exp((-z)*(z/2.0)); 
    double n = ((((b5*t+b4)*t+b3)*t+b2)*t+b1)*t; 
    n = 1.0-b*n; 
    if ( z < 0.0 ) n = 1.0 - n; 
    return n; 
}

double lognormalCumulativeProbability(double x, double mu, double sigma)
{
    return normalCumulativeProbabilty((Math.log(x) - mu) / sigma);
}

So what's this about "deal-or-no-deal"?
 
I like Serena said:
So what's this about "deal-or-no-deal"?

It's based on a game show.