具有高阶乘的泊松计算
Poisson Calc with high factorial
我有这段计算代码:
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" 方法中使用我的新阶乘方法?
问题是,我不能用 BigDecimal 双除...
感谢您的帮助:)
没有人:
我在一个使用 CalcPoisson 的方法中仍然有这行代码,我对 BigDecimal 仍然不好,我无法处理它。
线路:
BigDecimal nenner = CalcPoisson(m, u, false) + (1-p) * CalcPoisson(m, u, true);
您可以将您的双倍转换为 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;
假设您有 return 类型的方法 fakultaet()
是 BigDecimal。如果你有相同的 return 值 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)));
您可以从 Double 中创建一个新的 BigDecimal
然后你可以使用 BigDecimal
的 multiplie 方法
fct = fct.multiplie(new BigDecimal(doubleValue));
你的方法太直接了。此类循环通常以 while (nextTerm < epsilon)
的形式编写,而不是 for 循环。当然,前提是您可以证明项确实随着 i
.
而减少
另一个问题是虽然表达式 pow(u,i) / factorial(i)
的值可能适合双精度数,但它的部分肯定不适合。您需要以不同的方式计算它。当然,这样做会失去精度,所以会变得更加复杂。
我最好停下来。我的数学教授承诺他会追捕并杀死我们任何试图进行计算数学的人,他是一位严肃的绅士。
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;
}
最后,您还可以将术语和事实合并为一个参数(留给学生作为练习)。
我有这段计算代码:
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" 方法中使用我的新阶乘方法? 问题是,我不能用 BigDecimal 双除...
感谢您的帮助:)
没有人:
我在一个使用 CalcPoisson 的方法中仍然有这行代码,我对 BigDecimal 仍然不好,我无法处理它。
线路:
BigDecimal nenner = CalcPoisson(m, u, false) + (1-p) * CalcPoisson(m, u, true);
您可以将您的双倍转换为 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;
假设您有 return 类型的方法 fakultaet()
是 BigDecimal。如果你有相同的 return 值 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)));
您可以从 Double 中创建一个新的 BigDecimal
然后你可以使用 BigDecimal
fct = fct.multiplie(new BigDecimal(doubleValue));
你的方法太直接了。此类循环通常以 while (nextTerm < epsilon)
的形式编写,而不是 for 循环。当然,前提是您可以证明项确实随着 i
.
另一个问题是虽然表达式 pow(u,i) / factorial(i)
的值可能适合双精度数,但它的部分肯定不适合。您需要以不同的方式计算它。当然,这样做会失去精度,所以会变得更加复杂。
我最好停下来。我的数学教授承诺他会追捕并杀死我们任何试图进行计算数学的人,他是一位严肃的绅士。
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;
}
最后,您还可以将术语和事实合并为一个参数(留给学生作为练习)。