Poisson Calc具有高阶因子

时间:2016-08-17 17:15:02

标签: java poisson

我有这段代码用于计算:

    public static double CalcPoisson(double m, double u, boolean va)
{
    double answer = 0;
    if(!va)
    {
        answer = (Math.exp(-u)* Math.pow(u, m)) / (factorial(m));
    }
    if(va)
    {
        for(int i = 0; i < m; i++)
        {
            answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
        }
    }

    return answer;

这是我的因子方法

    public static double factorial (double n)
{
    return n == 0 ? 1 : n *factorial(n-1);
}

问题是:要计算的最大值是170 ......我需要更多的方法(比如500的阶乘)

我写了一个新方法:

    public static BigDecimal factorial2 (double n)
{
    BigDecimal fct = BigDecimal.valueOf(1);
    for(int i = 1; i<=n; i++)
    {
        fct = fct.multiply(BigDecimal.valueOf(i));
    }

    return fct;

如何在我的“CalcPoisson”方法中使用我的新factorial方法? 问题是,我不能用BigDecimal加倍...

感谢您的帮助:)

对于没有人:

我在一个使用CalcPoisson的方法中仍有这行代码,我仍然不能使用BigDecimal,我无法处理它。

The Line:

        BigDecimal nenner = CalcPoisson(m, u, false) + (1-p) * CalcPoisson(m, u, true);

4 个答案:

答案 0 :(得分:2)

for(int i = 0; i < m; i++)
{
    answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
}

请注意,此算法会计算从0到m-1的所有因子。更准确,更准确地说明这一点:

   long fact = 1;
    for(int i = 0; i < m; i++) {
        answer = answer + (Math.exp(-u)* Math.pow(u, i)) / fact;
        fact *= (i+1);
    }

然后注意Math.exp(-u)在循环中是不变的,所以提取它:

long fact = 1;
double eu = Math.exp(-u);
for(int i = 0; i < m; i++) {
    answer = answer + (eu * Math.pow(u, i)) / fact;
    fact *= (i+1);
}

你也可以摆脱对Math.pow()的重复调用:

long fact = 1;
double eu = Math.exp(-u);
double term = u;
for(int i = 0; i < m; i++) {
    answer = answer + (eu * term) / fact;
    fact *= (i+1);
    term *= u;
}

最后,您还可以将术语和事实结合到一个参数中(作为学生的练习)。

答案 1 :(得分:1)

您可以从Double中创建一个新的BigDecimal 然后你可以使用BigDecimal的multiplie方法

fct = fct.multiplie(new BigDecimal(doubleValue));

答案 2 :(得分:0)

你的方法太直接了。这种循环通常用while (nextTerm < epsilon)表示,而不是for循环。当然,这是因为您可以证明条款确实随着i而减少。

另一个问题是虽然表达式pow(u,i) / factorial(i)的值可能适合双精度,但它的部分肯定不会。您需要以不同的方式计算它。当然,正如你所做的那样,你会失去精确度,因此它变得更加复杂。

我最好停下来。我的数学教授承诺,他会追捕并杀死任何一个试图进行计算数学的人,他是一位认真的绅士。

答案 3 :(得分:-1)

您可以将双倍转换为BigDecimal,然后按以下方式划分两个BigDecimal

BigDecimal answer = BigDecimal.ZERO;
BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i)));
answer = answer.add(myOwn.divide(factorial2(i)));

使用BigDecimal查找“因子”,就像您在factorial2()中所做的一样。

最后你的方法如下:

    public static BigDecimal CalcPoisson(double m, double u, boolean va)
{
BigDecimal answer = BigDecimal.ZERO;
if(!va)
{
    BigDecimal myOwn1 = new BigDecimal(Double.toString((Math.exp(-u)* Math.pow(u, m))));
    answer =  myOwn1.divide(fakultaet(m));
}
if(va)
{
    for(int i = 0; i < m; i++)
    {
        BigDecimal myOwn = new BigDecimal(Double.toString(Math.exp(-u)* Math.pow(u, i)));
        answer = answer.add(myOwn.divide(factorial2(i)));
    }
}

return answer;

假设您有返回类型的方法fakultaet()是BigDecimal。如果您有相同的返回值double,请尝试:

answer =  myOwn1.divide(new BigDecimal(fakultaet(m)));

修改

BigDecimal nenner = CalcPoisson(m, u, false).add((BigDecimal.ONE.subtract(new BigDecimal(p))).multiply( CalcPoisson(m, u, true)));