使用 BigDecimal 计算欧拉数

Calculating Eulers number using BigDecimal

我正在尝试通过对以下数列求和来编写一个近似 e 的程序:

e = 1 + (1 / 1!) + (1 / 2!) + (1 / 3!) .... + (1 / i!)

目前,我的代码如下所示:

public static void main(String[] args) {

        BigDecimal one = new BigDecimal(1);
        BigDecimal e = new BigDecimal(1.0);
        BigDecimal divisor = new BigDecimal(1.0);

        for (int i =  1; i <= 12; i++) {

            divisor = divisor.multiply(new BigDecimal(i));
            e = e.add(one.divide(divisor));

            System.out.println("e = " + e);

        }
    }

程序对 n <= 2 成功执行了计算 (1 / n!),但一旦 n >= 3,我就会收到一条错误消息。程序似乎无法处理大于 2 的除数。程序的输出是:

e = 2

e = 2.5

线程异常"main" java.lang.ArithmeticException:非终止十进制展开;没有可精确表示的十进制结果。在 java.math.BigDecimal.divide(未知来源)在 ch10.Chapter_10_E20_ApproximateE.main(Chapter_10_E20_ApproximateE.java:16)

我应该如何使用 BigDecimal class 来计算 e = 1 + (1 / 1!) + (1 / 2!) + (1 / 3!) .... + (1 / i!) ?

众所周知,除以 3 会得到一个小数形式的数字,它会一直持续下去。

0.5 / 3 = 0.166666666666666666666666666666666666666666666666666666666666666666....

这就像您在 BigDecimal 内部进行的划分,只是正在计算二进制形式的 ints。

您将需要一个 different overload of divide 来使用一个刻度(小数点后的小数位数)和舍入模式。这告诉 BigDecimal 要使用多少位数字以及停止时如何舍入。

e = e.add(one.divide(divisor, 20, RoundingMode.HALF_EVEN));

e 输出的最终估计:

e = 2.71828182828616856395

此错误的原因是 BigDecimal 正在尝试准确计算该值,但它无法做到这一点,因为 1/3 以 10 为基数永远重复。

要解决此问题,您需要定义精度和舍入模式。例如:

  e = e.add( one.divide(divisor, 20, RoundingMode.HALF_UP) );