为什么Java的Double.compare(double,double)实现方式如何呢?

时间:2009-11-12 23:55:45

标签: java comparison floating-point

我正在研究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)
}

这种实施的优点是什么?


编辑:“优点”是一个(非常)糟糕的选择。我想知道它是如何工作的。

4 个答案:

答案 0 :(得分:43)

解释在代码中的注释中。 Java对0.0-0.0以及“非数字”(NaN)都有双重值。您不能对这些值使用简单的==运算符。查看doubleToLongBits()来源和the Javadoc for the Double.equals() method

  

请注意,在大多数情况下,两个   类Doubled1d2的实例,   如果,d1.equals(d2)的值为true   并且只有在

d1.doubleValue() == d2.doubleValue()
     

也具有值true。然而,   有两个例外:

     
      
  • 如果d1d2都代表Double.NaN,那么equals方法会返回true,甚至   虽然Double.NaN == Double.NaN的值为false
  •   
  • 如果d1代表+0.0d2代表-0.0,反之亦然,则等值测试的值为false,即使+0.0 == -0.0 }具有值true
  •   
     

此定义允许哈希表正常运行。

答案 1 :(得分:40)

@ Shoover的答案是正确的(请阅读!),但还有更多的内容。

Double::equals状态为javadoc

  

“此定义允许哈希表正常运行。”

假设Java设计者决定在包装的equals(...)实例上使用与compare(...)相同的语义实现==double。这意味着equals()总是会为包裹的NaN返回false。现在考虑如果您尝试在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.
}

没有多大意义吗!

存在其他异常,因为-0.0+0.0具有不同的位模式但根据==相等。

因此,Java设计人员(正确的IMO)决定了我们今天使用的这些Double方法的更复杂(但更直观)的定义。

答案 2 :(得分:2)

优点是它是满足规范的最简单的代码。

新手程序员的一个共同特征是高估阅读源代码并低估阅读规范。在这种情况下,规范:

http://java.sun.com/javase/6/docs/api/java/lang/Double.html#compareTo%28java.lang.Double%29

...使行为和行为的原因(与equals()的一致性)完全清楚。

答案 3 :(得分:0)

该实现允许将实数定义为&lt; NaN和-0.0&lt; 0.0。