Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use in Java big double numbers?

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));
        }
    }
}
like image 980
Alex Avatar asked Jan 25 '26 06:01

Alex


2 Answers

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.

like image 197
Sergey Kalinichenko Avatar answered Jan 27 '26 19:01

Sergey Kalinichenko


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.

like image 31
BambooleanLogic Avatar answered Jan 27 '26 19:01

BambooleanLogic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!