Double.doubleToLongBits(x)的含义 [英] Meaning of Double.doubleToLongBits(x)
问题描述
我正在写一个类 Vec2D
,它代表一个二维向量。我将 x
和 y
存储在 double
s中。
当要求生成 equals(Object obj
和 hashCode()
,eclipse会生成以下内容:
@Override
public int hashCode(){
final int prime = 31;
int结果= 1;
长期温度;
temp = Double.doubleToLongBits(x);
结果=素数*结果+(int)(temp ^(temp> ;>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result +(int)(temp ^(temp>>> 32));
返回结果;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
返回false;
if(getClass()!= obj.getClass())
return false;
Vec2D other =(Vec2D) obj;
if(Double.doubleToLongBits(x)!= Double.doubleToLongBits(other.x))
返回false;
if(Double.doubleTo LongBits(y)!= Double.doubleToLongBits(other.y))
返回false;
返回true;
}
Double.doubleToLongBits(x )
?我不能简单地写 x!= other.x
吗?
简短答案:Eclipse使用 Double.doubleToLongBits ,因为这就是 Double.equals 可以:
结果为
true
当且仅当参数不是null
并且是一个Double对象,它表示doubl
e具有与此对象表示的double
相同的值。为此,当且仅当方法 double 值才被视为相同。 /docs/api/java/lang/Double.html#doubleToLongBits(double) rel = noreferrer>doubleToLongBits(double)
返回相同的<$
长答案: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
当且仅当x的值为NaN时,才是true
。
如您所见,两个双精度值可以与 ==
进行比较,但实际上在数学和哈希中使用时对应于不同的行为表格。因此,当编写一个生成的相等方法时,Eclipse假定只有当且仅当所有可以对它们执行的操作都相同时,或者(等效地)如果将它们自动装箱并与<$ c $进行比较,两个双精度数才相等。 c>等于方法。如果在 double
和 Double
之间进行切换,这尤其重要-相等属性在那里出现差异是特别出乎意料的。 / p>
当然,您可以随意偏离该假设:不管这是一个好主意,您都可以将特殊情况分配给许多可能的NaN表示形式,在这种情况下 Double.doubleToRawLongBits()
更适合您的 equals
和 hashCode
方法。同样,您的用例可能会将+0.0和-0.0的对象视为等效对象,并保证不能使用NaN值,在这种情况下,原始的 ==
比较可能对于等于
更好地工作(但是到那时,为 hashCode
模仿相同的条件变得困难)。
I am writing a class Vec2D
, representing a 2 dimensional vector. I store x
and y
in double
s.
When asked to generate equals(Object obj
and hashCode()
, eclipse generated this:
@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? Can I not simply write x != other.x
?
Short answer: Eclipse uses Double.doubleToLongBits because that's what Double.equals does:
The result is
true
if and only if the argument is notnull
and is a Double object that represents adoubl
e that has the same value as thedouble
represented by this object. For this purpose, twodouble
values are considered to be the same if and only if the methoddoubleToLongBits(double)
returns the identicallong
value when applied to each.
Long answer: the JLS specifies a few differences between Double.equals and ==. For one difference specified in JLS 4.2.3 and JLS 15.21.1:
Positive zero and negative zero compare equal; thus the result of the expression
0.0==-0.0
istrue
and the result of0.0>-0.0
isfalse
. But other operations can distinguish positive and negative zero; for example,1.0/0.0
has the value positive infinity, while the value of1.0/-0.0
is negative infinity.
Another regards NaN
:
If either operand is NaN, then the result of
==
isfalse
but the result of!=
istrue
.Indeed, the test
x!=x
istrue
if and only if the value of x is NaN.
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. 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. This is particularly important if switching between double
and Double
—it would be particularly unexpected for equality properties to differ there.
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. 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).
这篇关于Double.doubleToLongBits(x)的含义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!