用Java更好地逼近e

问题描述 投票:6回答:8

我想把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
java math precision
8个回答
13
投票

使用一个 大十进制 而不是双倍。

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

6
投票

你的主要问题是 double 的精度非常有限。如果你想要任意的精度,你将不得不使用 BigDecimal. 下一个问题你会遇到的是有限的范围内的 long 在这里你可以使用 BigInteger.


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
投票

如果你从49数到1,而不是像现在这样从1数到49,你会得到更好的结果。


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 

1
投票

更多的性能建议有人知道吗?

是的,你对因子的计算效率太低了。 最好是把它移到你求和项的循环里面。 你的做法把一个O(N)问题变成了一个O(N^2)问题。

如果这是一个真正的计算,需要阶乘,我建议用表格查找或不完全伽马函数作为正确的方法。

从性能的角度来看,你唯一能做得更差的就是递归的阶乘计算。 那么你就会有一个额外的问题,那就是巨大的堆栈。


0
投票

要理解为什么你不能用以下方法获得 "任何想要的精度"。double,阅读这篇经典论文。

《每个计算机科学家都应该知道的浮点算术》。

请注意,这是一篇技术性很强的论文。更多关于浮点数字工作原理的基本细节,请看维基百科的文章。双精度浮点格式


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
...
© www.soinside.com 2019 - 2024. All rights reserved.