比较Java中的双精度会产生奇怪的结果
我真的无法理解为什么会发生以下情况:
Double d = 0.0; System.out.println(d == 0); // is true System.out.println(d.equals(0)); // is false ?!
然而,这可以按预期工作:
Double d = 0.0; System.out.println(d == 0.0); // true System.out.println(d.equals(0.0)); // true
我很肯定这在某种程度上与自动装箱有关,但我真的不知道为什么在使用==
运算符和调用.equals
时为什么0
会被加框 。
这不是暗示违反了equals
合同吗?
*它是自反的:对于任何非空参考值 * x,x.equals(x)应该返回 *是的。
编辑 :
谢谢你的快速答案。 我认为它的盒装方式不同,真正的问题是:它为什么装箱不同? 我的意思是,如果d == 0d
比d.equals(0d)
更直观和预期,这将更直观,但是如果d == 0
看起来像一个Integer
是true
比’直觉’ d.equals(0)
也应该是真的。
只需将其更改为
System.out.println(d.equals(0d)); // is false ?! now true
你正在将double与Integer
0进行比较
在封面下
System.out.println(d.equals(0)); // is false ?!
0
将自动装箱到Integer
, Integer
一个实例将被传递给Double
类的equals()
方法,它将在
@Override public boolean equals(Object object) { return (object == this) || (object instanceof Double) && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value)); }
当然会返回虚假 。
更新
当您使用==
进行比较时,它会比较值,因此不需要autobox,它直接对值进行操作。 where equals()
接受Object
所以如果你试图调用d1.equals(0)
, 0
就不是Object,所以它会执行自动装箱,并将它打包到Integer,这是一个Object。
Number
对象类型相同,则数字对象仅等于具有相同值的数字。 那是:
new Double(0).equals(new Integer(0)); new BigInteger("0").equals(new BigDecimal("0"));
和类似的组合都是假的。
在您的情况下,文字0
被装入一个Integer
对象。
值得注意的是,你应该像这样比较浮点数:
|x - y| < ε, ε very small
d.equals(0)
: 0
是一个int
。 Double.equals()
代码仅对Double
对象返回true。
当你表演
d == 0
这是向上倾斜的
d == 0.0
然而,没有自动装箱的上行规则,即使有等号(对象)没有给出你想要的双击而不是整数的命中。