Search code examples
javabigdecimal

BigDecimal - unexpected round behaviour


I think I have found a bug:

MathContext mathContext = new MathContext(5, RoundingMode.HALF_UP);
result = BigDecimal.valueOf(0.004798).round(mathContext); // fails
// result is 0.004798!!! (same value)

I had to use the following alternative:

BigDecimal bigDecimal = BigDecimal.valueOf(0.004798);
BigDecimal new_divisor = BigDecimal.valueOf(1, 5);
bigDecimal_array = bigDecimal.divideAndRemainder(new_divisor);
MathContext mathContext = new MathContext(5, RoundingMode.HALF_UP);
result = bigDecimal.subtract(bigDecimal_array[1], mathContext);
result = result.stripTrailingZeros();

This bug (if it is so) is very dangerous in my opinion.


Solution

  • No, there's no bug. You're just misunderstanding what "precision" means.

    From BigDecimal's documentation

    the total number of digits to return is specified by the MathContext's precision setting; this determines the result's precision. The digit count starts from the leftmost nonzero digit of the exact result.

    (emphasis mine).

    You have 4 digits in this case. So any precision greater then or equal to 4 will have no effect on rounding.

    Compare with

    result = BigDecimal.valueOf(0.004798).round(new MathContext(3, RoundingMode.HALF_UP));
    result ==> 0.00480
    

    or with

    jshell> result = BigDecimal.valueOf(1.004798).round(new MathContext(5, RoundingMode.UP));
    result ==> 1.0048
    

    Which behave like you expect.