Question

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?

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));
        }
    }
}
Was it helpful?

Solution

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

You need to convert all your aX variables to BigDecimal, and replace operators with calls to the corresponding methods of BigDecimal class:

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.

OTHER TIPS

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

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top