- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在用 Java 编写一个复数类,如下所示:
public class Complex {
public final double real, imag;
public Complex(double real, double imag) {
this.real = real;
this.imag = imag;
}
... methods for arithmetic follow ...
}
我这样实现了 equals 方法:
@Override
public boolean equals(Object obj) {
if (obj instanceof Complex) {
Complex other = (Complex)obj;
return (
this.real == other.real &&
this.imag == other.imag
);
}
return false;
}
但是如果您覆盖 equals,您也应该覆盖 hashCode。规则之一是:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
比较 float
和 double
与 ==
进行数值比较,所以 +0.0 == -0.0
和 NaN 值不等于所有内容,包括它们自身。所以我尝试实现 hashCode 方法来匹配 equals 方法,如下所示:
@Override
public int hashCode() {
long real = Double.doubleToLongBits(this.real); // harmonize NaN bit patterns
long imag = Double.doubleToLongBits(this.imag);
if (real == 1L << 63) real = 0; // convert -0.0 to +0.0
if (imag == 1L << 63) imag = 0;
long h = real ^ imag;
return (int)h ^ (int)(h >>> 32);
}
但后来我意识到,如果其中一个字段为 NaN,这在 HashMap 中会很奇怪地工作,因为 this.equals(this)
将始终为 false,但也许这不是错误的。另一方面,我可以做 Double
和 Float
做的事情,其中 equals 方法比较 +0.0 != -0.0
,但仍然协调不同的 NaN 位模式,并让 NaN == NaN
,所以我得到:
@Override
public boolean equals(Object obj) {
if (obj instanceof Complex) {
Complex other = (Complex)obj;
return (
Double.doubleToLongBits(this.real) ==
Double.doubleToLongBits(other.real) &&
Double.doubleToLongBits(this.imag) ==
Double.doubleToLongBits(other.imag)
);
}
return false;
}
@Override
public int hashCode() {
long h = (
Double.doubleToLongBits(real) +
Double.doubleToLongBits(imag)
);
return (int)h ^ (int)(h >>> 32);
}
但如果我这样做,那么我的复数就不会表现得像实数,其中 +0.0 == -0.0
。但无论如何,我真的不需要将我的复数放在 HashMap 中——我只想做正确的事,遵循最佳实践等。现在我只是感到困惑。任何人都可以建议我继续进行的最佳方式吗?
最佳答案
这个我想多了。问题源于试图平衡 equals 的两种用法:IEEE 754 算术比较和对象/哈希表比较。对于浮点类型,由于 NaN,这两种需求永远无法同时满足。算术比较需要 NaN != NaN
,但对象/哈希表比较(equals 方法)需要 this.equals(this)
。
Double
根据Object
的约定正确实现方法,所以NaN == NaN
。它还执行 +0.0 != -0.0
。这两种行为都与原始 float/double 类型的比较相反。
java.util.Arrays.equals(double[], double[])
比较元素的方式与 Double
相同(NaN == NaN
, +0.0 != -0.0
).
java.awt.geom.Point2D
在技术上是错误的。它的 equals 方法仅将坐标与 ==
进行比较,因此 this.equals(this)
可以为假。同时,它的 hashCode 方法使用 doubleToLongBits
,因此即使 equals 返回 true,它的 hashCode 对于两个对象也可以不同。该文档没有提及细微之处,这意味着问题并不重要:人们不会将这些类型的元组放入哈希表中! (如果他们这样做了,效果也不会很好,因为您必须完全得到相同的数字才能得到相同的 key 。)
在像复数类这样的浮点元组中,equals 和 hashCode 最简单的正确实现是完全不覆盖它们。如果您希望方法考虑值,那么正确的做法是 Double
所做的:使用 doubleToLongBits
(或 floatToLongBits
)在这两种方法中。如果这不适合算术,则需要一个单独的方法;也许 equals(Complex other, double epsilon)
比较数字在公差范围内是否相等。
请注意,您可以覆盖 equals(Complex other)
而不会干扰 equals(Object other)
,但这似乎太困惑了。
关于java - 复数等于法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18856530/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我有实体: @Entity @Table(name = "CARDS") public class Card { @ManyToOne @JoinColumn(name = "PERSON_I
我正在尝试计算二维多边形的表面法线。我正在使用 OpenGL wiki 中的 Newell 方法来计算表面法线。 https://www.opengl.org/wiki/Calculating_a_S
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我这里有以下 XML: Visa, Mastercard, , , , 0, Discover, American Express siteonly, Buyer Pay
即将发生的 Google 政策变更迫使我们实现一个对话框,以通知欧盟用户有关 Cookie/设备标识符用于广告和分析的情况。我只想向欧盟用户显示此对话框。我不想使用额外的权限(例如 android.p
本文分享自华为云社区《华为大咖说 | 企业应用AI大模型的“道、法、术” ——道:认知篇》,作者:华为云PaaS服务小智。 本期核心观点 上车:AGI是未来5~10年内,每个人都无法回避的技
我有一个与酒精相关的网站,需要先验证年龄,然后才能让他们进入该网站。我使用 HttpModule 来执行此操作,该模块检查 cookie,如果未设置,我会将它们重定向到验证页面。我验证他们的年龄并存储
在欧盟,我们有一项法律,要求网页请求存储 cookie 的许可。我们大多数人都了解 cookie 并同意它们,但仍然被迫在任何地方明确接受它们。所以我计划编写这个附加组件(ff & chrome),它
以下在 C 和/或 C++ 中是否合法? void fn(); inline void fn() { /*Do something here*/ } 让我担心的是,第一个声明看起来暗示函数将被定义
我是一名优秀的程序员,十分优秀!