我想将e的值近似为任何所需的精度。做这个的最好方式是什么?我能得到的最多是e = 2.7182818284590455。有关修改以下代码的任何示例都将不胜感激。
public static long fact(int x){
long prod = 1;
for(int i = 1; i <= x; i++)
prod = prod * i;
return prod;
}//fact
public static void main(String[] args) {
double e = 1;
for(int i = 1; i < 50; i++)
e = e + 1/(double)(fact(i));
System.out.print("e = " + e);
}//main
答案 0 :(得分:13)
使用BigDecimal代替双倍。
BigDecimal e = BigDecimal.ONE;
BigDecimal fact = BigDecimal.ONE;
for(int i=1;i<100;i++) {
fact = fact.multiply(new BigDecimal(i));
e = e.add(BigDecimal.ONE.divide(fact, new MathContext(10000, RoundingMode.HALF_UP)));
}
答案 1 :(得分:6)
您的主要问题是double
的精确度非常有限。如果您想要任意精度,则必须使用BigDecimal
。您将遇到的下一个问题是long
的有限范围,您可以使用阶乘法快速超过该范围 - 您可以使用BigInteger
。
答案 2 :(得分:4)
您是否看过java.util.BigDecimal
中的任意精度算术?
import java.math.BigDecimal;
import java.math.MathContext;
public class BigExp {
public static void main(String[] args) {
BigDecimal FIFTY =new BigDecimal("50");
BigDecimal e = BigDecimal.ZERO;
BigDecimal f = BigDecimal.ONE;
MathContext context = new MathContext(1000);
for (BigDecimal i=BigDecimal.ONE; i.compareTo(FIFTY)<0; i=i.add(BigDecimal.ONE)) {
f = f.multiply(i, context);
e = e.add(i.divide(f,context),context);
System.out.println("e = " + e);
}
}
}
答案 3 :(得分:3)
如果从现在开始计算从49到1而不是1到49,您将获得更好的结果。
答案 4 :(得分:1)
使用了Zed和mobrule代码的变体。工作得很好,谢谢!任何人都有更多的表现建议吗?
public static BigDecimal factorial(int x){
BigDecimal prod = new BigDecimal("1");
for(int i = x; i > 1; i--)
prod = prod.multiply(new BigDecimal(i));
return prod;
}//fact
public static void main(String[] args) {
MathContext mc = new MathContext(1000);
BigDecimal e = new BigDecimal("1", mc);
for(int i = 1; i < 1000; i++)
e = e.add(BigDecimal.ONE.divide(factorial(i), mc));
System.out.print("e = " + e);
}//main
答案 5 :(得分:1)
更多性能建议吗?
是的,你对factorial的计算效率低得多。最好将它移到你正在总结术语的循环中。你正在做事的方式将O(N)问题转化为O(N ^ 2)问题。
如果这是一个需要阶乘的真实计算,我建议使用表格查找或不完整的伽马函数作为正确的方法。
从性能的角度来看,唯一可以做得更糟的是递归因子计算。然后你会遇到额外的堆叠问题。
答案 6 :(得分:0)
要了解为什么无法使用double
获得“任何所需的精确度”,请阅读此经典论文:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
请注意,这是一篇非常技术性的论文。有关浮点数如何工作的更多基本细节,请参阅此维基百科文章:Double precision floating-point format
答案 7 :(得分:0)
使用BigDecimal类可以获得e的最佳近似值。
这是用于计算给定的BigDecimal值的代码
import java.math.BigDecimal;
import java.math.MathContext;
public class ApproximateE {
public static void main(String[] args) {
System.out.println("e~ "+e(new BigDecimal(50)));//the value to approximate
}
static BigDecimal e(BigDecimal n) {
BigDecimal num = new BigDecimal(n + "");
BigDecimal e = BigDecimal.ZERO;
BigDecimal f = BigDecimal.ONE;
MathContext context = new MathContext(25);//digits of precision
/************************************************************************
The formula for approximating e ~
e = 1+(1/1!+1/2!+1/3!...1/i!)
************************************************************************/
for (BigDecimal i = BigDecimal.ONE; i.compareTo(num) < 0; i = i.add(BigDecimal.ONE)) {
f = f.multiply(i, context);
e = e.add(i.divide(f, context), context);
}
return e;
}
}
返回:
e~ 2.718281828459045235360289
f的值为
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
51090942171709440000
1124000727777607680000
25852016738884976640000
620448401733239439360000
1.551121004333098598400000E+25
4.032914611266056355840000E+26
1.088886945041835216076800E+28
3.048883446117138605015040E+29
8.841761993739701954543616E+30
2.652528598121910586363085E+32
8.222838654177922817725564E+33
2.631308369336935301672180E+35
8.683317618811886495518194E+36
2.952327990396041408476186E+38
1.033314796638614492966665E+40
3.719933267899012174679994E+41
1.376375309122634504631598E+43
5.230226174666011117600072E+44
2.039788208119744335864028E+46
8.159152832478977343456112E+47
3.345252661316380710817006E+49
1.405006117752879898543143E+51
6.041526306337383563735515E+52
2.658271574788448768043627E+54
1.196222208654801945619632E+56
5.502622159812088949850307E+57
2.586232415111681806429644E+59
1.241391559253607267086229E+61
6.082818640342675608722522E+62
e的值为
1
2
2.5
2.666666666666666666666667
2.708333333333333333333334
2.716666666666666666666667
2.718055555555555555555556
2.718253968253968253968254
2.718278769841269841269841
2.718281525573192239858906
2.718281801146384479717813
2.718281826198492865159532
2.718281828286168563946342
2.718281828446759002314558
2.718281828458229747912288
2.718281828458994464285470
2.718281828459042259058794
2.718281828459045070516048
2.718281828459045226708118
2.718281828459045234928753
2.718281828459045235339785
2.718281828459045235359358
2.718281828459045235360248
2.718281828459045235360287
2.718281828459045235360289
2.718281828459045235360289
...