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;
}