0

I recently made a basic Pi calculator that works with Math.BigDecimal. It outputs to a text file, and calculates extremely fast, but even BigDecimal has it's limits. I was wondering what the basic code would be for numbers even more precise (Not that any code would actually need that). Here is the Pi code:

    package mainPack;
    import java.io.IOException;
    import java.math.BigDecimal;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.Scanner;
    public class Main {
    public static BigDecimal piDigCalc(int i){
        double o = (double)i;
        BigDecimal ret = new BigDecimal((1/(Math.pow(16.0D, o))*((4/((8*o) + 1))-(2/((8*o) + 4))-(1/((8*o) + 5))-(1/((8*o)+6))))); //Just the code for a hexdigit of Pi.
        return ret;
    }
    public static void main(String[] args) throws IOException {
        System.out.println("Enter accuracy:");
        Scanner s = new Scanner(System.in);
        int acc = s.nextInt();
        s.close();
        BigDecimal Pi = new BigDecimal(0);
        for(int i = 0; i < acc; i++){
                Pi = Pi.add(piDigCalc(i));
        }
        Path file = Paths.get("C:\\tmp\\PI.txt");
        String pi = "" + Pi;
        Files.write(file, pi.getBytes());
            System.out.println("File has been saved at "+ file.toString());
    }
}
  • `BigDecimal` is almost arbitrary precision. It supports up to 2 billion decimal digits to the right of the decimal point, and unlimited digits to the left. If you're having issues, it's probably because of what you're doing in `piDigCalc`, specifically: `double o = (double) i;` which will introduce errors because doubles are not perfectly precise. – Wug Jul 10 '13 at 20:46
  • Ok thanks. I didn't really know how else to turn i into a double, so... yeah. But I had no idea it supported that many digits... – user2570097 Jul 10 '13 at 20:51
  • Turn it into an arbitrary precision type instead. – Wug Jul 10 '13 at 20:53

1 Answers1

0

I rewrote your piDigCalc function to use entirely arbitrary precision values. You can see it running on ideone (1300 was about the largest precision I could get to finish under ideone's 15 second time limit).

It is in no way optimized, it's just a verbatim translation of the math in your code to bigdecimals.

You might notice that there is actually a precision limit to the values, but this is partly because setting huge limits increases runtime by a lot. The limit I set scales with the provided accuracy.

In case ideone ever explodes, here's the code for piDigCalc:

public static BigDecimal piDigCalc(int _i, int x){
    BigDecimal
        i = BigDecimal.valueOf(_i),
        a = SIXTEEN.pow(_i),
        b = EIGHT.multiply(i),
        c = ONE.divide(a, x, BigDecimal.ROUND_HALF_EVEN),
        d = b.add(ONE), // b + 1
        e = b.add(FOUR), // b + 4
        f = e.add(ONE), // b + 5
        g = f.add(ONE), // b + 6
        h = FOUR.divide(d, x, BigDecimal.ROUND_HALF_EVEN),
        j = TWO.divide(e, x, BigDecimal.ROUND_HALF_EVEN),
        k = ONE.divide(f, x, BigDecimal.ROUND_HALF_EVEN),
        l = ONE.divide(g, x, BigDecimal.ROUND_HALF_EVEN),
        m = h.subtract(j).subtract(k).subtract(l),
        n = c.multiply(m);

    return n;
}

The constants ONE, TWO, FOUR, EIGHT, SIXTEEN are defined static to the class and have exact integer values (ONE also exists as a constant in BigDecimal).

Wug
  • 12,956
  • 4
  • 34
  • 54