在Java中比较double会得到奇怪的结果
我真的无法理解为什么会发生以下情况:在Java中比较double会得到奇怪的结果,java,double,equals,autoboxing,Java,Double,Equals,Autoboxing,我真的无法理解为什么会发生以下情况: 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 我肯定这在某种程度上与自动
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合同吗
* It is reflexive: for any non-null reference value
* x, x.equals(x) should return
* true.
*它是自反的:对于任何非空的引用值
*x,x.equals(x)应该返回
*对。
编辑:
谢谢你的快速回答。我认为它的装箱方式不同,真正的问题是:为什么它的装箱方式不同?我的意思是,如果
d==0d
比d.equals(0d)
更直观,但是如果d==0
看起来像Integer
是true
比d.equals(0)更直观
也应为true。数字
对象只有在其类型相同时才等于具有相同值的数字。即:
new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));
类似的组合都是错误的
在您的例子中,文本0
被装箱到一个Integer
对象中。只需将其更改为
System.out.println(d.equals(0d)); // is false ?! now true
您将double与Integer
0进行比较
在封面下
0
将自动装箱到Integer
中,Integer的一个实例将被传递到equals()
方法的Double
类中,在那里它将进行类似的比较
@Override
public boolean equals(Object object) {
return (object == this)
|| (object instanceof Double)
&& (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
}
当然,它将返回false
更新
当您使用
==
进行比较时,它会比较值,因此不需要自动装箱,它直接对值进行操作。其中equals()
接受Object
,因此如果您尝试调用d1.equals(0)
,0
不是Object,因此它将执行自动装箱,并将其打包为作为对象的整数。d.equals(0)
:0
是一个int
。Double.equals()
d == 0
这是向上的
d == 0.0
但是,自动装箱没有向上转换的规则,即使有equals(Object),也不会给出想要双精度而不是整数的命中率。可能值得注意的是,您应该像这样比较浮点数:
|x - y| < ε, ε very small
| x-y |<ε,ε非常小
或仅仅满足于d==0
?:)@Simeon在评论中回答了您的问题,当d
是一个对象而0是基元时,它如何比较值?在它取消装箱d
(到int
?或者可能使用Double.doubleValue()
?)或框0时,我看不出它如何对对象和原语执行=
。也许我应该问一个单独的问题,因为这个问题有点纠结…它将调用d.doubleValue()==0
,请在@Simeon中阅读更多关于它的内容:这不是JVM特定的,因为它是由JLS指定的。Jigar Joshi,很抱歉之前的评论,我很困惑;您正在谈论取消装箱转换,但是您应该提到(5.1.8)。0
是一个int
,将自动装箱为一个Integer
@Joachim Sauer,这都是假定的:)但是OP显然不明白。把这些事情说清楚是个好主意。为什么在调用.equals时它会把它框成整数,在调用==时它会把它框成其他的东西?@Simeon因为equals()
acceptObject
,勾选@Jigar我确实读过你的答案(我甚至投了赞成票),但让我感到奇怪的是,当我们进行==
比较时,0被装箱到Double
(或者是吗?!甚至在==比较上发生了什么,应该创建一个对象,以便它可以正确地比较引用?)当我们做.equals
时,它被装箱为整数
,所以它实际上根本没有装箱==它的刚转换,这就是我想要的答案。如果正确的值不是0.0,比如0.2323121212,我想你的答案更好。
|x - y| < ε, ε very small