T.Setso T.Setso - 3 months ago 16
C Question

Poisson calculation (erlang C)

i posted this before, user told me to post it on codereview. i did, and they closed it...so one more time here: (i deleted the old question)

I have these formulas:
http://i.stack.imgur.com/nZzLd.png

and I need the Poisson formulas for the erlangC formula:

http://www.mitan.co.uk/erlang/elgcpois.gif

I tried to rebuild the formulas in C:

double getPoisson(double m, double u, bool cumu)
{
double ret = 0;
if(!cumu)
{
ret = (exp(-u)*pow(u,m)) / (factorial(m));
}
else
{
double facto = 1;
double ehu = exp(-u);
for(int i = 0; i < m; i++)
{
ret = ret + (ehu * pow(u,i)) / facto;
facto *= (i+1);
}
}
return ret;
}


The Erlang C Formula:

double getErlangC(double m, double u, double p)
{
double numerator = getPoisson(m, u, false);
double denominator = getPoisson(m, u, false) + (1-p) * getPoisson(m, u, true);
return numerator/denominator;
}


The main problem is, the
m
parameter in
getPoisson
is a big value (>170)
so it wants to calculate >170! but it cannot handle it. I think the primitive data types are too small to work correctly, or what do you say?

BTW: This is the factorial function I use for the first Poisson:

double factorial(double n)
{
if(n >= 1)
return n*factorial(n-1);
else
return 1;
}


Some samples:

Input:

double l = getErlangC(50, 48, 0.96);
printf("%g", l);


Output:

0.694456 (correct)


Input:

double l = getErlangC(100, 96, 0.96);
printf("%g", l);


Output:

0.5872811 (correct)


if i use a value higher than 170 for the first parameter (m) of getErlangC like:

Input:

double l = getErlangC(500, 487, 0.974);
printf("%g", l);


Output:

naN (incorrect)


Excepted:

0.45269


How's my approach? Would be there a better way to calculate Poisson and erlangC?

Some Info: Excel has the POISSON Function, and on Excel it works perfekt... would there be a way to see the algorithm(code) EXCEL uses for POISSON?

Answer

(pow(u, m)/factorial(m)) can be expressed as a recursive loop with each element shown as u/n where each n is an element of m!.

double ratio(double u, int n)
{
    if(n > 0)
     {
        // Avoid the ratio overflow by calculating each ratio element
        double val;
        val = u/n;
        return val*ratio(u, n-1);
      }
    else
      {
         // Avoid division by 0 as power and factorial of 0 are 1
        return 1;
      }
}

Note that if you want to avoid recursion, you can do it as a loop as well

double ratio(double u, int n)
{
    int i;
    // Avoid the ratio overflow by calculating each ratio element
    // default the ratio to 1 for n == 0
    double val = 1;
    // calculate the next n-1 ratios and put them into the total
    for (i = 1; i<=n; i++)
      {
        // Put in the next element of the ratio 
        val *=  u/n;
      }
    // return the final value of the ratio
    return val;
}
Comments