views:

350

answers:

2

As the Ordered trait demands, the equals method on Scala's BigDecimal class is consistent with the ordering. However, the hashcode is simply taken from the wrapped java.math.BigDecimal and is therefore inconsistent with equals.

object DecTest {
  def main(args: Array[String]) {
    val d1 = BigDecimal("2")
    val d2 = BigDecimal("2.00")
    println(d1 == d2) //prints true
    println(d1.hashCode == d2.hashCode) //prints false
  }
}

I can't find any reference to this being a known issue. Am I missing something?

A: 

Update: This answer is wrong! I've left it up because I think the comments are useful in seeing why it's wrong.


This isn't an example of a violation of the equals/hashCode contract. You would need to check whether d1.equals(d2) is equal to prove that. And indeed, d1.equals(d2) returns false. Why?

It's because "2" isn't precisely the same thing as "2.00"; the value on the right has more significant digits. In other words, they are equal in value (2 == 2.00), but differ in scale (0 != 2).

If you read the source code here, you can see that for two numbers, it falls through to the Java BigDecimal equals implementation. Then, reading the Java documentation describes how this works in greater detail.

John Feminella
Whoever is upvoting this needs to go and read about Scala! `==` in Scala is equivalent to `.equals` in Java. **This answer is wrong**
oxbow_lakes
*@John* - have you tried running your answer in Scala? It is not correct! `scala.BigDecimal` and `java.math.BigDecimal` are different things
oxbow_lakes
*@John* - sorry to carp on: if you follow your link, you can see that the `equals` method falls through to Java's `BigDecimal.compare` method
oxbow_lakes
@oxbow_lakes » Whoops, you're right. I actually made two mistakes, since I somehow ran this in Groovy (where it works) instead of in Scala. That'll teach me to answer without sufficient caffeine. Also, I think you meant compareTo, right?
John Feminella
> you can see that for two numbers, it falls through to the Java `BigDecimal` `equals` implementationNo. Actually, you can see `def equals (that: BigDecimal): Boolean = this.bigDecimal.compareTo(that.bigDecimal) == 0`
Alexey Romanov
+5  A: 

The people over on the Scala User mailing list seem to agree that this is a bug. I guess it's not been picked up until now because no-one has ever used a BigDecimal as a key in a hash structure. It's been filed as bug #2304

oxbow_lakes

related questions