Reputation: 23
import java.math.BigDecimal
BigDecimal(0.235).setScale(2, BigDecimal.ROUND_HALF_UP) // 0.23
BigDecimal("0.235").setScale(2, BigDecimal.ROUND_HALF_UP) // 0.24
In kotlin, when input 0.235 is given as double then the output is 0.23. when input 0.235 is given as string then the output is 0.24
Here is the definition of ROUND_HALF_UP given in the documentation:
Rounding mode where values are rounded towards the nearest neighbor. Ties are broken by rounding up.
Upvotes: 1
Views: 3672
Reputation: 23091
From the BigDecimal
docs:
- The results of this constructor can be somewhat unpredictable. One might assume that writing new
BigDecimal(0.1)
in Java creates aBigDecimal
which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.- The String constructor, on the other hand, is perfectly predictable: writing
new BigDecimal("0.1")
creates aBigDecimal
which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
Upvotes: 2
Reputation: 520878
The issue here is that in the first case you are calling the BigDecimal
constructor using a floating point (read: not exact) literal. Consider the following script (in Java):
BigDecimal blah = new BigDecimal(0.235d);
System.out.println(blah);
This prints 0.23499999999999998667732370449812151491641998291015625
in my demo tool. That is, you are not actually passing in literal 0.235
, but rather a floating point approximation to it. It so happens, in this case, that the actual literal value is slightly less than 0.235
, leading the round half up to result in 0.23
rather than 0.24
.
Upvotes: 0