最近我用 Java 编写了一个项目,并注意到双/双实现的一个非常奇怪的特性。Java 中的 double 类型有两个 0,即 0.0 和 -0.0(带符号的零)。奇怪的是:
0.0 == -0.0
计算结果为true
,但是:
new Double(0.0).equals(new Double(-0.0))
评估为false
。有谁知道这背后的原因?
这一切都在javadoc中进行了解释:
请注意,在大多数情况下,对于 Double 类的两个实例 d1 和 d2,d1.equals(d2) 的值当且仅当
d1.doubleValue() == d2.doubleValue()
也有值 true。但是,有两个例外:
- 如果 d1 和 d2 都表示 Double.NaN,则 equals 方法返回 true,即使 Double.NaN==Double.NaN 的值为 false。
- 如果 d1 表示 +0.0 而 d2 表示 -0.0,或者反之亦然,则相等测试的值为 false,即使 +0.0==-0.0 的值为 true。
此定义允许哈希表正常运行。
现在你可能会问为什么0.0 == -0.0
是真的。事实上,它们并不完全相同。例如:
Double.doubleToRawLongBits(0.0) == Double.doubleToRawLongBits(-0.0); //false
是假的。但是,JLS要求(“根据 IEEE 754 标准的规则”):
正零和负零被认为是相等的。
因此0.0 == -0.0
是真的。
了解 Double 类中带符号零的使用很重要。(大量有经验的 Java 程序员没有)。
简短的回答是(根据定义)在 Double 类提供的所有方法(即 equals()、compare()、compareTo() 等)中“-0.0 小于 0.0”
Double 允许所有浮点数“在数轴上完全排序”。基元的行为方式与用户思考事物的方式相同(现实世界的定义)... 0d = -0d
以下片段说明了行为...
final double d1 = 0d, d2 = -0d;
System.out.println(d1 == d2); //prints ... true
System.out.println(d1 < d2); //prints ... false
System.out.println(d2 < d1); //prints ... false
System.out.println(Double.compare(d1, d2)); //prints ... 1
System.out.println(Double.compare(d2, d1)); //prints ... -1
还有其他相关的帖子很好地解释了背景......
2:为什么Java的 Double.compare(double, double) 是这样实现的?
还有一句警告...
如果您不知道在 Double 类中"-0.0 is less than 0.0" ,那么在逻辑测试中使用 Double 中的equals()和compare()和compareTo()等方法时,您可能会被抓到。例如,看...
final double d3 = -0d; // try this code with d3 = 0d; for comparison
if (d3 < 0d) {
System.out.println("Pay 1 million pounds penalty");
} else {
System.out.println("Good things happen"); // this line prints
}
if (Double.compare(d3, 0d) < 0) { //use Double.compare(d3, -0d) to match the above behaviour
System.out.println("Pay 1 million pounds penalty"); // this line prints
} else {
System.out.println("Good things happen");
}
对于equals,您可以尝试... new Double(d3).equals(0d) || 新双(d3)。等于(-0d)
通过使用 == 语句,您可以比较值。使用等于您正在比较对象。