Non-Terminating Decimal Error Even With MathContex

2019-06-18 22:33发布

I'm crafting code to implement this algorithm:

formula

However, I'm getting this error, even with MathContext(1000):

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1603)
at picalculator.PiCalculator.calculatePi(PiCalculator.java:59)
at picalculator.PiCalculator.main(PiCalculator.java:25)
Java Result: 1

While using this method:

public static void calculatePi() {
    BigInteger firstFactorial;
    BigInteger secondFactorial;
    BigInteger firstMultiplication;
    BigInteger firstExponent;
    BigInteger secondExponent;
    int firstNumber = 1103;
    BigInteger firstAddition;
    BigDecimal currentPi = BigDecimal.ONE;
    BigDecimal pi = BigDecimal.ONE;
    BigDecimal one = BigDecimal.ONE;
    int secondNumber = 2;
    double thirdNumber = Math.sqrt(2.0);
    int fourthNumber = 9801;
    BigDecimal prefix = BigDecimal.ONE;

    for(int i=1;i<4;i++){
        firstFactorial = factorial(4*i);
        secondFactorial = factorial(i);
        firstMultiplication = BigInteger.valueOf(26390*i);
        firstExponent = exponent(secondFactorial, 4);
        secondExponent = exponent(BigInteger.valueOf(396),4*i);
        firstAddition = BigInteger.valueOf(firstNumber).add(firstMultiplication);
        currentPi = currentPi.add(new BigDecimal(firstFactorial.multiply(firstAddition)).divide(new BigDecimal(firstExponent.multiply(secondExponent)), new MathContext(10000)));
    }

    prefix =new BigDecimal(secondNumber*thirdNumber);
    prefix = prefix.divide(new BigDecimal(fourthNumber), new MathContext(1000));

    currentPi = currentPi.multiply(prefix, new MathContext(1000));

    pi = one.divide(currentPi);

    System.out.println("Pi is: " + pi);

    return;
}

I have proven that factorial(a); and exponent(a,b) return the factorial of a and the result of a^b respectively, accurately.

Does anyone know how to fix this?

标签: java pi
2条回答
We Are One
2楼-- · 2019-06-18 23:27

You might prefer to use different version of divide. It gives you more control over the final scale of the returned BigDecimal. Whereas, with your version the final scale depends on the scale of the dividend and divisor.

int scale = 3;
BigDecimal result = ONE.divide(new BigDecimal("3"), scale, RoundingMode.HALF_UP);
// result is 0.333
查看更多
倾城 Initia
3楼-- · 2019-06-18 23:34

You need

pi = one.divide(currentPi, new MathContext(1000));

Since the result is almost certainly a repeating decimal.

Consider

BigDecimal a = new BigDecimal("4");
BigDecimal b = new BigDecimal("3");

BigDecimal c = a.divide(b)                         // java.lang.ArithmeticException: Non-terminating decimal expansion
BigDecimal c = a.divide(b, new MathContext(10));   // No exception
查看更多
登录 后发表回答