问题 Double.doubleToLongBits(x)的含义


我正在上课 Vec2D,表示二维向量。我存储 x 和 y 在 double秒。

当被要求生成时 equals(Object obj 和 hashCode(),eclipse产生了这个:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(x);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    temp = Double.doubleToLongBits(y);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Vec2D other = (Vec2D) obj;
    if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
        return false;
    if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
        return false;
    return true;
}

有什么意义 Double.doubleToLongBits(x) 在这种背景下?我不能简单地写 x != other.x


2998
2018-05-02 23:38


起源



答案:


简短回答:Eclipse使用 Double.doubleToLongBits 因为那是什么 Double.equals 作用:

结果是 true 当且仅当论证不是 null 并且是一个代表一个的Double对象 double具有与...相同的值 double 由此对象表示。为此目的,两个 double 当且仅当方法时,值被认为是相同的 doubleToLongBits(double) 返回相同的 long 应用于每个时的值。

答案很长:JLS指定了Double.equals和==之间的一些差异。对于指定的一个差异 JLS 4.2.3 和 JLS 15.21.1

正零和负零比较相等;因此表达的结果 0.0==-0.0 是 true 和结果 0.0>-0.0 是 false。但其他操作可以区分正负零;例如, 1.0/0.0 具有正无穷大的值,而具有正值的无穷大 1.0/-0.0 是负无穷大。

另一个问候 NaN

如果任一操作数是NaN,则结果为 == 是 false 但结果 != 是 true

的确,测试 x!=x 是 true 当且仅当x的值是NaN时。

如你看到的, 可以将两个双值进行比较 == 但实际上对应于在数学和哈希表中使用时的不同行为。因此,在编写生成的相等方法时,Eclipse假设两个双精度只有当且仅当所有可以对它们执行的操作相同时,或者(等效地)如果它们被自动装箱并与它们进行比较时才是相等的。 equals 方法。如果在之间切换,这一点尤为重要 double 和 Double - 对于那里的平等属性而言,这将是特别出乎意料的。

当然,你可以自由地偏离这个假设:不管这是一个好主意,你可以将特殊情况分配给许多可能的NaN表示中的任何一个,在这种情况下 Double.doubleToRawLongBits() 将是一个更好的匹配你的 equals 和 hashCode 方法。出于同样的原因,您的用例可能会将+0.0和-0.0的对象视为等效对象,并保证NaN值不可能,在这种情况下是原始的 == 比较可能更好 equals (但在此时仿效相同的标准 hashCode 变得困难)。


11
2018-05-03 00:52





因为 == 和 != 按照IEEE-754语义进行双打, Double.NaN != Double.NaN 和 0.0 == -0.0。这些行为可能不是你想要的,所以 Double.doubleToLongBits() 转换64位 double 数据为64位 long 数据,以便像位移和XOR一样的操作。

老实说,不过,我会说使用 doubleToLongBits 这是一个错误,因为如果你关心你应该使用的确切的平等 Double.doubleToRawLongBits()(不执行任何翻译 double 相反,数据。


3
2018-05-03 00:51





快速浏览一下在线javadoc会产生这样的结果:

根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示形式。

...

在所有情况下,结果都是一个长整数,当给予longBitsToDouble(long)方法时,将生成一个与doubleToLongBits参数相同的浮点值(除了所有NaN值都折叠为单个“规范”NaN)值)。

所以它可能是一种标准化的方式 double 的陈述 x 和 y,因为NaN可以有多个 double 交涉


0
2018-05-03 00:48