如何在Java中使用大双数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20240275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:30:17  来源:igfitidea点击:

How to use in Java big double numbers?

javabigdecimalpi

提问by Alex

I've found a solution for calculating number of Pi by using BBS algorithm. But I encountered a problem. I'm missing a precision if using a double variable. Is there any suggestion to fix it?

我找到了一种使用 BBS 算法计算 Pi 数的解决方案。但是我遇到了一个问题。如果使用双变量,我会缺少精度。有什么建议可以解决它吗?

Here is my code:

这是我的代码:

public class Pi {
    public static void main(String[] args) {
        int n = 5;

        for (int k = 0; k < n; k++) {
            int a0 = (int) Math.pow(16, k);

            double a1 = (double) 4 / (8 * k + 1);
            double a2 = (double) 2 / (8 * k + 4);
            double a3 = (double) 1 / (8 * k + 5);
            double a4 = (double) 1 / (8 * k + 6);

            double a5 = a1 - a2 - a3 - a4;
            double a6 = (double) 1 / a0;
            double elem = a5 * a6;

            System.out.println(new BigDecimal(elem));
        }
    }
}

采纳答案by dasblinkenlight

If you need the precision of BigDecimal, you need to use it for all calculations. It is not sufficient to convert the result from doubleto BigDecimalat the end, because the precision is gone by then.

如果需要 的精度BigDecimal,则需要将其用于所有计算。这是不够的结果,从转换doubleBigDecimal结尾,因为精度地方了。

You need to convert all your aXvariables to BigDecimal, and replace operators with calls to the corresponding methods of BigDecimalclass:

您需要将所有aX变量转换为BigDecimal,并将运算符替换为对BigDecimal类的相应方法的调用:

BigDecimal pi = BigDecimal.ZERO;
for (int k = 0; k < n; k++) {
    BigDecimal a0 = new BigDecimal(16).pow(k);
    BigDecimal a1 = new BigDecimal(4).divide(new BigDecimal(8*k+1), 20, RoundingMode.HALF_UP);
    BigDecimal a2 = new BigDecimal(2).divide(new BigDecimal(8*k+4), 20, RoundingMode.HALF_UP);
    BigDecimal a3 = new BigDecimal(1).divide(new BigDecimal(8*k+5), 20, RoundingMode.HALF_UP);
    BigDecimal a4 = new BigDecimal(1).divide(new BigDecimal(8*k+6), 20, RoundingMode.HALF_UP);
    BigDecimal a5 = a1.subtract(a2).subtract(a3).subtract(a4);
    BigDecimal a6 = BigDecimal.ONE.divide(a0, 20, RoundingMode.HALF_UP);
    pi.add(a5.multiply(a6));
    System.out.println(pi);
}

Demo on ideone.

ideone 上的演示

回答by Smallhacker

The problem is that you're using doubles during the calculation itself, thus inevitably losing accuracy. Yes, you're using BigDecimalat the end, but only after already destroying data by putting it in doubles.

问题是您在计算过程中使用了双打,因此不可避免地会失去准确性。是的,您在最后使用BigDecimal,但只有在通过将数据放入双打来破坏数据之后才使用。

The solution is to not use doubles at ANY point in the calculation. Use BigDecimalfor every step of the way.

解决方案是在计算中的任何一点都不使用双精度数。使用BigDecimal了的每一步。

To use a metaphor: What you're doing is trying to pour a swimming pool's amount of water into a glass, then pouring the glass into the pool and expecting it to be filled. No, it won't be, because most of the water didn't fit in the glass and just poured onto the ground.

用一个比喻:你正在做的是试图将游泳池的水量倒入玻璃杯中,然后将玻璃杯倒入游泳池并期待它被充满。不,它不会,因为大部分水都装不进玻璃杯,只是倒在地上。