-->

Non-Terminating Decimal Error Even With MathContex

2019-06-18 22:57发布

问题:

I'm crafting code to implement this algorithm:

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?

回答1:

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


回答2:

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


标签: java pi