Berkin
Berkin

Reputation: 1654

Weird side effect when rounding BigDecimals

I am trying to use only the 8 digits after the floating point and round the rest to the ceiling. When the input is 0.0, after the rounding operation, I have 0E-8 instead of 0.00000000

val test = BigDecimal.valueOf(0.0)
println(test.setScale(8, RoundingMode.CEILING))    

When I change the value with 2.0 the result is fine as I expected 2.00000000

I am new at Kotlin. I don't understand the reason.

Upvotes: 1

Views: 82

Answers (1)

Sweeper
Sweeper

Reputation: 270770

Whether toString returns the number in exponential notation or not is documented here:

first, the absolute value of the unscaled value of the BigDecimal is converted to a string in base ten using the characters '0' through '9' with no leading zeros (except if its value is zero, in which case a single '0' character is used).

Next, an adjusted exponent is calculated; this is the negated scale, plus the number of characters in the converted unscaled value, less one. That is, -scale+(ulength-1), where ulength is the length of the absolute value of the unscaled value in decimal digits (its precision).

If the scale is greater than or equal to zero and the adjusted exponent is greater than or equal to -6, the number will be converted to a character form without using exponential notation. [...]

Otherwise (that is, if the scale is negative, or the adjusted exponent is less than -6), the number will be converted to a character form using exponential notation. [...]

In the 0 case, the unscaled value is "0", according to the documentation. This has the length of 1. Therefore, the adjusted exponent is -8 + (1 - 1) = -8. This is less than -6, so it is displayed in exponential notation.

When the number is 2, the unscaled value is "200000000", and the scale of 8 scales it down it "2.00000000". The unscaled value has a length of 9. Therefore, the adjusted exponent is -8 + (9 - 1) = 0. This is greater than -6, and the scale of 8 is greater than 0, so 2.00000000 is not displayed in exponential notation.

Note that you can always get a string that is not in exponential notation by calling toPlainString.

Upvotes: 6

Related Questions