Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if a BigDecimal is in a Set or Map in a scale independent way?

BigDecimal's equals() method compares scale too, so

new BigDecimal("0.2").equals(new BigDecimal("0.20")) // false

It's contested why it behaves like that.

Now, suppose I have a Set<BigDecimal>, how do I check if 0.2 is in that Set, scale independent?

Set<BigDecimal> set = new HashSet<>();
set.add(new BigDecimal("0.20"));
...
if (set.contains(new BigDecimal("0.2")) { // Returns false, but should return true
    ...
}
like image 687
Geoffrey De Smet Avatar asked Nov 20 '13 09:11

Geoffrey De Smet


1 Answers

contains() will work as you want it to if you switch your HashSet to a TreeSet.

It is different from most sets as it will decide equality based on the compareTo() method as opposed to equals() and hashCode():

a TreeSet instance performs all element comparisons using its compareTo (or compare) method

And since BigDecimal.compareTo() compares without regard to scale, that's exactly what you want here.

Alternatively you could ensure that all elements in the Set are of the same, minimal scale, by always using stripTrailingZeros (both on add() and on contains()):

set.add(new BigDecimal("0.20").stripTrailingZeros());
...
if (set.contains(new BigDecimal("0.2").stripTrailingZeros()) {
  ...
}
like image 78
Joachim Sauer Avatar answered Sep 28 '22 06:09

Joachim Sauer