Dav*_*idS 35 java floating-point comparison
我正在研究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)
}
Run Code Online (Sandbox Code Playgroud)
这个实现的优点是什么?
编辑:"优点"是一个(非常)糟糕的选择.我想知道它是如何工作的.
sho*_*ver 43
解释在代码中的注释中.Java有两个双值0.0和-0.0,以及"不是一个数字"( NaN).您不能==对这些值使用简单运算符.看一下doubleToLongBits()源代码和方法的JavadocDouble.equals():
请注意,在大多数情况下,类的两个实例
Double,d1并且d2,该值d1.equals(d2)是true当且仅当Run Code Online (Sandbox Code Playgroud)d1.doubleValue() == d2.doubleValue()也有价值
true.但是,有两个例外:
- 如果
d1和d2两者都表示Double.NaN,那么true即使Double.NaN == Double.NaN有值,equals方法也会返回false.- 如果
d1代表+0.0whiled2表示-0.0,反之亦然,则等值测试具有该值false,即使+0.0 == -0.0具有该值true.此定义允许哈希表正常运行.
Ste*_*n C 41
@ Shoover的答案是正确的(读它!),但它还有更多的东西.
由于javadoc中的Double::equals规定:
"这个定义允许哈希表正常运行."
假设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.
}
Run Code Online (Sandbox Code Playgroud)
这样做没有多大意义!
其他异常将存在,因为-0.0并且+0.0具有不同的位模式但是根据相同而不相同==.
因此,Java设计者(正确的IMO)决定了我们今天使用的这些Double方法的更复杂(但更直观)的定义.
| 归档时间: |
|
| 查看次数: |
48018 次 |
| 最近记录: |