简体   繁体   English

Double.doubleToLongBits(x)的含义

[英]Meaning of Double.doubleToLongBits(x)

I am writing a class Vec2D , representing a 2 dimensional vector. 我正在写一个类Vec2D ,代表一个二维向量。 I store x and y in double s. 我将xy存储在double s中。

When asked to generate equals(Object obj and hashCode() , eclipse generated this: 当被要求生成equals(Object objhashCode() ,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;
}

What is the significance of Double.doubleToLongBits(x) in this context? Double.doubleToLongBits(x)在此上下文中的意义是什么? Can I not simply write x != other.x ? 我不能简单地写x != other.x吗?

Short answer: Eclipse uses Double.doubleToLongBits because that's what Double.equals does: 简短回答:Eclipse使用Double.doubleToLongBits,因为这就是Double.equals的作用:

The result is true if and only if the argument is not null and is a Double object that represents a doubl e that has the same value as the double represented by this object. 其结果是true ,当且仅当参数不null ,并且是双对象,它表示一个doubl具有相同的值作为电子double该对象表示。 For this purpose, two double values are considered to be the same if and only if the method doubleToLongBits(double) returns the identical long value when applied to each. 为此,当且仅当方法doubleToLongBits(double)在应用于每个时返回相同的long值时,才认为两个double值相同。

Long answer: the JLS specifies a few differences between Double.equals and ==. 答案很长:JLS指定了Double.equals和==之间的一些差异。 For one difference specified in JLS 4.2.3 and JLS 15.21.1 : 对于JLS 4.2.3JLS 15.21.1中指定的一个差异:

Positive zero and negative zero compare equal; 正零和负零比较相等; thus the result of the expression 0.0==-0.0 is true and the result of 0.0>-0.0 is false . 因此,表达式0.0==-0.0的结果为true0.0>-0.0的结果为false But other operations can distinguish positive and negative zero; 但其他操作可以区分正负零; for example, 1.0/0.0 has the value positive infinity, while the value of 1.0/-0.0 is negative infinity. 例如, 1.0/0.0的值为正无穷大,而1.0/-0.0值为负无穷大。

Another regards NaN : 另一个问题是NaN

If either operand is NaN, then the result of == is false but the result of != is true . 如果任一操作数是NaN,则==的结果为false!=的结果为true

Indeed, the test x!=x is true if and only if the value of x is NaN. 实际上,当且仅当x的值是NaN时,测试x!=xtrue

As you can see, it's possible for two double values to compare with == but actually correspond to different behavior when used in math and hash tables . 正如您所看到的, 可以将两个double值与==进行比较,但实际上对应于在数学和哈希表中使用时的不同行为 Thus, when writing a generated equality method, Eclipse makes the assumption that two doubles are only equal if and only if all operations that can be done to them are identical, or (equivalently) if they were autoboxed and compared with their equals methods. 因此,在编写生成的相等方法时,Eclipse假设只有当所有可以对它们执行的操作相同时,或者(等效地)它们被自动装箱并与它们的equals方法进行比较时,两个双精度才相等。 This is particularly important if switching between double and Double —it would be particularly unexpected for equality properties to differ there. 如果在doubleDouble之间切换特别意外的话,对于不同的等同属性,这一点尤为重要。

Of course, you're free to drift from that assumption: Regardless of whether it's a good idea, you may assign special cases to any of the many possible NaN representations, in which case Double.doubleToRawLongBits() would be a better match for your equals and hashCode methods. 当然,你可以自由地偏离这个假设:不管它是否是一个好主意,你可以将特殊情况分配给许多可能的NaN表示中的任何一个,在这种情况下, Double.doubleToRawLongBits()将更适合你的equalshashCode方法。 By the same token, your use case might treat objects with +0.0 and -0.0 as equivalent and guarantee that NaN values are not possible, in which case a raw == comparison may work better for equals (but at which point emulating the same criteria for hashCode becomes difficult). 出于同样的原因,您的用例可能会将+0.0和-0.0的对象视为等效对象,并保证NaN值不可能,在这种情况下,原始==比较可能对equals更好(但在此时仿效相同的条件)对于hashCode变得困难)。

Because == and != follow IEEE-754 semantics for doubles, Double.NaN != Double.NaN and 0.0 == -0.0 . 因为==!=遵循IEEE-754双精度语义, Double.NaN != Double.NaN0.0 == -0.0 These behaviors may not be what you want, so Double.doubleToLongBits() converts the 64 bits of double data to 64 bits of long data so that operations like bit shifts and XOR work. 这些行为可能不是您想要的,因此Double.doubleToLongBits()将64位double数据转换为64位long数据,以便像位移和XOR这样的操作。

Honestly, though, I would say that the use of doubleToLongBits is a bug here, since if you care about exact equality you should be using Double.doubleToRawLongBits() (which does not perform any translations on the double data at all) instead. 老实说,我会说使用doubleToLongBits是一个错误,因为如果你关心完全相等,你应该使用Double.doubleToRawLongBits() (它根本不对double数据执行任何翻译)。

A quick glance at the online javadoc yields this: 快速浏览一下在线javadoc会产生这样的结果:

Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout. 根据IEEE 754浮点“双格式”位布局返回指定浮点值的表示形式。

... ...

In all cases, the result is a long integer that, when given to the longBitsToDouble(long) method, will produce a floating-point value the same as the argument to doubleToLongBits (except all NaN values are collapsed to a single "canonical" NaN value). 在所有情况下,结果都是一个长整数,当给予longBitsToDouble(long)方法时,将生成一个与doubleToLongBits参数相同的浮点值(除了所有NaN值都折叠为单个“规范”NaN)值)。

So it's probably a way of standardizing the double representations of x and y , as NaN can have multiple double representations 因此,它可能是标准化xydouble表示的一种方式,因为NaN可以具有多个double表示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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