Reputation: 1
I am getting an unexpected result I want to remove numbers after two number of decimal point
BigDecimal(0.55).setScale(2, RoundingMode.FLOOR) //return 0.55
BigDecimal(0.56).setScale(2, RoundingMode.FLOOR) //return 0.56
BigDecimal(0.57).setScale(2, RoundingMode.FLOOR) //return 0.56
BigDecimal(**0.58**).setScale(2, RoundingMode.FLOOR) //return 0.57
BigDecimal(**0.59**).setScale(2, RoundingMode.FLOOR) //return 0.58
BigDecimal(**0.60**).setScale(2, RoundingMode.FLOOR) //return 0.59
BigDecimal(**0.61**).setScale(2, RoundingMode.FLOOR) //return 0.60
BigDecimal(**0.62**).setScale(2, RoundingMode.FLOOR) //return 0.61
BigDecimal(0.63).setScale(2, RoundingMode.FLOOR) //return 0.63
Upvotes: 0
Views: 1796
Reputation: 18537
The problem here is not in the setScale()
call, but happens before that. You're constructing the BigDecimal
from a Double
value — a value which is close to 0.58, but isn't exactly.
(FLoat
s and Double
s are binary floating-point — and almost no decimal fractions have an exact binary representation. In this case, 0.58 is 0.10010100011110101110000101… in binary. No Double
can store that exactly; the best if can do is store a value very close to it.)
The BigDecimal
then does its best to store that value as precisely as possible. You can see this in the REPL:
>>> java.math.BigDecimal(0.58)
res1: java.math.BigDecimal = 0.57999999999999996003197111349436454474925994873046875
…which makes it obvious why that rounds down to 0.57, not 0.58.
And that holds for all of your problem cases: the nearest Double
is slightly less than the decimal value you specify, and so rounds down. (In the others, it's slightly greater, so those round as expected. But the underlying problem is still there.)
The best solution is to avoid floating-point binary numbers entirely, and use the BigDecimal(String)
constructor:
>>> java.math.BigDecimal("0.58").setScale(2, java.math.RoundingMode.FLOOR)
res6: java.math.BigDecimal! = 0.58
(In this case, of course, there's no longer a need for the setScale()
call at all, as the value now has a scale of 2 already! But it does no harm.)
Upvotes: 2
Reputation: 7788
You fell victim of double floating point precision. When you write
0.62
in reallity it's actually something like
0.6199999999999626787363666...
.
You should use BigDecimal
constructor that takes String
instead of Double
argument.
Upvotes: 3