Java 符号零和装箱
最近我用Java写了一个项目,注意到一个非常奇怪的功能,带有double/Double实现。Java中的双精度类型有两个0,即0.0和-0.0(有符号零)。奇怪的是:
0.0 == -0.0
计算结果为 ,但:true
new Double(0.0).equals(new Double(-0.0))
计算结果为 。有谁知道这背后的原因吗?false
最近我用Java写了一个项目,注意到一个非常奇怪的功能,带有double/Double实现。Java中的双精度类型有两个0,即0.0和-0.0(有符号零)。奇怪的是:
0.0 == -0.0
计算结果为 ,但:true
new Double(0.0).equals(new Double(-0.0))
计算结果为 。有谁知道这背后的原因吗?false
这一切都在javadoc中进行了解释:
请注意,在大多数情况下,对于双子类 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 程序员不会这样做)。
简短的回答是(根据定义)“-0.0小于0.0”在Double类提供的所有方法中(即equals(),compare(),compareTo()等)
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
还有其他相关的帖子,并很好地解释了背景...
1: 为什么浮点数有符号零?
2: 为什么Java的Double.compare(double,double)是这样实现的?
还有一句警告...
如果你不知道,在 Double 类中,“-0.0 小于 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");
}
对于平等,您可以尝试...新的 Double(d3).equals(0d) ||新的双精度(d3).等于(-0d)