为什么 Java 的 Double.compare(double, double) 是这样实现的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1726254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is Java's Double.compare(double, double) implemented the way it is?
提问by DavidS
I was looking at the implementation of compare(double, double)in the Java standard library (6). It reads:
我正在查看Java 标准库 (6)中compare(double, double)的实现。它写道:
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
What are the merits of this implementation?
这种实现的优点是什么?
edit: "Merits" was a (very) bad choice of words. I wanted to know how this works.
编辑:“优点”是一个(非常)糟糕的词选择。我想知道这是如何工作的。
采纳答案by Stephen C
@Shoover's answer is correct (read it!), but there is a bit more to it than this.
@Shoover 的答案是正确的(阅读它!),但还有更多内容。
As the javadocfor Double::equals
states:
由于javadoc中的Double::equals
规定:
"This definition allows hash tables to operate properly."
“这个定义允许哈希表正常运行。”
Suppose that the Java designers had decided to implement equals(...)
and compare(...)
with the same semantics as ==
on the wrapped double
instances. This would mean that equals()
would always return false
for a wrapped NaN. Now consider what would happen if you tried to use a wrapped NaN in a Map or Collection.
假设Java的设计者已经决定实施equals(...)
和compare(...)
使用相同的语义==
上的包裹double
的情况。这意味着它equals()
总是会返回false
一个包裹的 NaN。现在考虑如果您尝试在 Map 或 Collection 中使用包装的 NaN 会发生什么。
List<Double> l = new ArrayList<Double>();
l.add(Double.NaN);
if (l.contains(Double.NaN)) {
// this wont be executed.
}
Map<Object,String> m = new HashMap<Object,String>();
m.put(Double.NaN, "Hi mum");
if (m.get(Double.NaN) != null) {
// this wont be executed.
}
Doesn't make a lot of sense does it!
没有多大意义吧!
Other anomalies would exist because -0.0
and +0.0
have different bit patterns but are equal according to ==
.
其他异常现象会存在,因为-0.0
和+0.0
有不同的位模式,但根据是相等的==
。
So the Java designers decided (rightly IMO) on the more complicated (but more intuitive) definition for these Double methods that we have today.
因此,Java 设计者决定(正确地 IMO)对我们今天拥有的这些 Double 方法进行更复杂(但更直观)的定义。
回答by phoebus
That implementation allows a real number to be defined as < NaN, and -0.0 as < 0.0.
该实现允许将实数定义为 < NaN,将 -0.0 定义为 < 0.0。
回答by shoover
The explanation is in the comments in the code. Java has double values for both 0.0
and -0.0
, as well as "not a number" (NaN
). You can't use simple ==
operator for these values. Take a peek into the doubleToLongBits()
source and at the Javadoc for the Double.equals()
method:
解释在代码的注释中。Java 对0.0
and-0.0
以及“非数字” ( NaN
)都有双重值。您不能==
对这些值使用简单运算符。查看该方法的doubleToLongBits()
源代码和JavadocDouble.equals()
:
Note that in most cases, for two instances of class
Double
,d1
andd2
, the value ofd1.equals(d2)
istrue
if and only ifd1.doubleValue() == d2.doubleValue()
also has the value
true
. However, there are two exceptions:
- If
d1
andd2
both representDouble.NaN
, then the equals method returnstrue
, even thoughDouble.NaN == Double.NaN
has the valuefalse
.- If
d1
represents+0.0
whiled2
represents-0.0
, or vice versa, the equal test has the valuefalse
, even though+0.0 == -0.0
has the valuetrue
.This definition allows hash tables to operate properly.
请注意,在大多数情况下,类的两个实例
Double
,d1
并且d2
,该值d1.equals(d2)
是true
当且仅当d1.doubleValue() == d2.doubleValue()
也有价值
true
。但是,有两个例外:
- 如果
d1
和d2
都表示Double.NaN
,则 equals 方法返回true
,即使Double.NaN == Double.NaN
具有值false
。- 如果
d1
代表+0.0
whiled2
代表-0.0
,反之亦然,则相等测试具有值false
,即使+0.0 == -0.0
具有值true
。此定义允许哈希表正常运行。
回答by Kevin Bourrillion
The merit is that it's the simplest code that fulfills the specification.
优点是它是满足规范的最简单的代码。
One common characteristic of rookie programmers is to overvalue reading source code and undervalue reading specifications. In this case, the spec:
菜鸟程序员的一个共同特征是高估阅读源代码而低估阅读规范。在这种情况下,规范:
http://java.sun.com/javase/6/docs/api/java/lang/Double.html#compareTo%28java.lang.Double%29
http://java.sun.com/javase/6/docs/api/java/lang/Double.html#compareTo%28java.lang.Double%29
... makes the behavior and the reason for the behavior(consistency with equals()) perfectly clear.
... 使行为和行为的原因(与 equals() 的一致性)非常清楚。