Lognormal cumulative distribution function for JavaScript?

  • Thread starter moonman239
  • Start date
  • #1
282
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.)
 

Answers and Replies

  • #2
I like Serena
Homework Helper
6,577
176
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]
 
  • #3
282
0
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:
  • #4
I like Serena
Homework Helper
6,577
176
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 [Broken]

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:
  • #5
I like Serena
Homework Helper
6,577
176
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"?
 
  • #7
282
0

Related Threads on Lognormal cumulative distribution function for JavaScript?

  • Last Post
3
Replies
61
Views
8K
  • Last Post
Replies
4
Views
5K
Replies
3
Views
2K
Replies
1
Views
2K
  • Last Post
Replies
0
Views
4K
Replies
6
Views
8K
  • Last Post
Replies
1
Views
7K
Replies
4
Views
4K
Replies
12
Views
749
Top