Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dividing BigDecimals results in ArithmeticException [duplicate]

Tags:

java

math

Possible Duplicate:
ArithmeticException thrown during BigDecimal.divide

This results in ArithmeticException: http://ideone.com/RXeZw

Providing a scale and rounding mode will give me the wrong result. This example should output 50.03%. How to round this correctly?

For easier reference, this is the code:

BigDecimal priceDiff = BigDecimal.ONE
     .subtract(new BigDecimal(9.99)
     .divide(new BigDecimal(19.99)))
     .multiply(new BigDecimal(100));
System.out.println(priceDiff.toPlainString());
like image 377
dtrunk Avatar asked Aug 29 '12 12:08

dtrunk


2 Answers

BigDecimal.divide(BigDecimal divisor) throws an ArithmeticException if the result cannot be exactly represented.
You will have to use provide a MathContext or a RoundingMode telling how you want to handle this. For example:

public class Test {
    public static void main(String[] args) throws java.lang.Exception {
        BigDecimal priceDiff = BigDecimal.ONE.subtract(new BigDecimal("9.99").divide(new BigDecimal("19.99"), MathContext.DECIMAL128))
                                             .multiply(new BigDecimal(100));
        System.out.println(priceDiff.toPlainString());
    }
}

works and prints

50.0250125062531265632816408204102100

Also, note the use of the BigDecimal(String) constructor to avoid problems when you create BigDecimal using a double literal.

like image 51
Keppil Avatar answered Sep 18 '22 01:09

Keppil


You should use a MathContext as your division as an infinite number of decimals:

    BigDecimal priceDiff = BigDecimal.ONE
            .subtract(new BigDecimal(9.99)
            .divide(new BigDecimal(19.99), new MathContext(10, RoundingMode.UP)))
            .multiply(new BigDecimal(100));
    System.out.println(priceDiff.toPlainString());

However, that prints 50.025...

This would print 49.98:

BigDecimal priceDiff = new BigDecimal(9.99)
        .divide(new BigDecimal(19.99), new MathContext(10, RoundingMode.UP))
        .multiply(new BigDecimal(100), new MathContext(4, RoundingMode.UP));
System.out.println(priceDiff.toPlainString());
like image 22
assylias Avatar answered Sep 22 '22 01:09

assylias