简体   繁体   中英

Does Scala's BigDecimal violate the equals/hashCode contract?

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?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM