I've just recently come across a behavior inside BigDecimal
that I wasn't previously aware of. I've always used them as an alternative to double for areas where precision is important. For example in financial calculations.
However I recently came across this fact
new BigDecimal("1.0").equals(new BigDecimal("1")) == false
I have to admit I was surprised by this. I figure it is because the first has a scale of 1 while the second has a scale of 0, but still it seems counter-intuitive. I think the reason I've never run into it before is because we've always used fixed scale BigDecimals
for financial calculations.
Checking the BigDecimal
documentation I can see that says that compareTo() == 0
should be used to check for equality ignoring scale while that equals()
compares both the value and the scale.
Are there any other similar gotchas I should be aware of when using BigDecimal
s with different scales?
If you need to use division in your arithmetic, you need to use double instead of BigDecimal.
valueOf() has the more intuitive behaviour, while new BigDecimal(d) has the more correct one. Try both and see the difference.
compareTo(BigDecimal bg) method checks for equality of this BigDecimal and BigDecimal object bg passed as parameter. The method considers two equal BigDecimal objects even if they are equal in value irrespective of the scale.
equals() method checks for equality of a BigDecimal value with the object passed. This method considers two BigDecimal objects equal if only if they are equal in value and scale.
There is a value and a scale of the BigDecimal. Both need to be equal for the BigDecimals to be equal. From the java docs . . .
Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).
https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#equals(java.lang.Object)
BigDecimal equals checks that the contents of the two BigDecimal object are the same. e.g. their toString() would be the same. Just as "1.0" and "1" are not equal, nor is new BigDecimal("1.0").equals(new BigDecimal("1"))
as the unscaledValue()
and getScale()
are both different.
The catch is that while you knew that ==
wouldn't compare the contents and you might have been told .equals
is the solution for String
, it may not do what you intended for BigDecimal.
For compareTo
it has to work on what is greater than or less than and since the values are neither greater than or less than they can only be equal (but not equals).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With