Scala 的 BigDecimal 是否违反了 equals/hashCode 契约?

发布于 2024-08-02 17:29:50 字数 440 浏览 7 评论 0原文

根据 Ordered trait 的要求,Scala 的 BigDecimal 类上的 equals 方法与排序一致。但是,哈希码只是从包装的 java.math.BigDecimal 中获取,因此与 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
  }
}

我找不到任何关于此已知问题的参考。我错过了什么吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁〃客ぐ 2024-08-09 17:29:50

Scala 用户邮件列表上的人们似乎都同意这是一个错误。我想它直到现在才被采用,因为没有人使用过 BigDecimal 作为哈希结构中的键。它已归档为 bug #2304

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

若沐 2024-08-09 17:29:50

更新:这个答案是错误的!我把它保留下来是因为我认为这些评论对于了解为什么它是错误的很有用。


这不是违反 equals/hashCode 合约的示例。您需要检查 d1.equals(d2) 是否等于来证明这一点。事实上,d1.equals(d2) 返回 false。为什么?

这是因为“2”与“2.00”并不完全相同;右边的值有更多的有效数字。换句话说,它们的相等(2 == 2.00),但比例不同(0 != 2)。

如果您阅读源代码 在这里,您可以看到对于两个数字,它会落入 Java BigDecimal equals 实现。然后,阅读 Java 文档更详细地描述了其工作原理。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文