Java 高阶乘泊松计算

Java 高阶乘泊松计算,java,poisson,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++)

我有一段计算代码:

    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;
问题是:要计算的最大值是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;

您可以将double转换为
BigDecimal
,然后可以将两个
BigDecimal
s除以,如下所示:

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;
编辑

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

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

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

你的方法太直接了。这样的循环通常以
的形式编写,而(nexterm
的形式编写,而不是以for循环的形式编写。当然,也就是说,前提是您可以证明这些术语确实随着
i
而减少

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

我最好停下来。我的数学教授承诺,他将追捕并杀死我们中任何试图做计算数学的人,他是一位严肃的绅士。

for(int i=0;ifor(int i = 0; i < m; i++)
{
    answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
}
{ 答案=答案+(数学表达式(-u)*数学功率(u,i))/(阶乘(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);
    }
长事实=1;
for(int i=0;i
然后注意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);
}
长事实=1;
双eu=数学表达式(-u);
for(int i=0;i
您还可以消除对Math.pow()的重复调用:

长事实=1;
双eu=数学表达式(-u);
双项=u;
for(int i=0;i

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

什么不适用于
double
?所有的东西,包括你的最终结果,都是双精度的,如果你需要更多的代码<代码> BigDecimal < /代码>值在你的等式中间是没有帮助的。问题的方法是阶乘直到170!因此,我们的想法是,使用everywhere BigDecimal而不是double?is(1-p)是BigDecimal?我的意思是
p
is BigDecimal?@T.Setso我已经编辑了我的答案。@T.Setso欢迎:)如果答案有用,你可以将答案标记为正确:)另一个问题:另一个方法的一行是:'BigDecimal nenner=calcPoisson(m,u,false)+(1-p)*calcPoisson(m,u,true);'现在的问题是,*不是为BigDecimal定义的,无论你在哪里看到星号(*),你都可以使用.multiply()来表示BigDecimal和BigInteger。如果你仍然得到错误,请在问题中发布该方法。我会尽力帮忙的@为了你的评论,我知道我的算法编码不好。。我会努力学习把它做得更好:)谢谢你的评论,我知道我的算法编码不好。。我会努力学着做得更好:)
for(int i = 0; i < m; i++)
{
    answer = answer + (Math.exp(-u)* Math.pow(u, i)) / (factorial(i));
}
   long fact = 1;
    for(int i = 0; i < m; i++) {
        answer = answer + (Math.exp(-u)* Math.pow(u, i)) / fact;
        fact *= (i+1);
    }
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);
}
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;
}