比较 Java 中的双精度数会得到奇怪的结果

发布于 2024-10-21 08:10:22 字数 877 浏览 1 评论 0原文

我真的无法理解为什么会发生以下情况:

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

我确信这在某种程度上与自动装箱有关,但我真的不知道为什么0== 运算符和调用 .equals 时,code> 的装箱方式会有所不同

这不是隐含地违反了equals契约吗?

  *  It is reflexive: for any non-null reference value
  *     x, x.equals(x) should return
  *     true.

编辑

感谢您的快速答复。我认为它的装箱方式不同,真正的问题是:为什么它的装箱方式不同?我的意思是,如果 d == 0dd.equals(0d) 更直观且符合预期,但是如果 d == 0 code> 看起来像 Integertrue 而“直观地”d.equals(0) 也应该是 true。

I really can'get my head around why the following happens:

Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!

This however works as expected:

Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true

I'm positive that this is related to autoboxing in some way, but I really don't know why 0 would be boxed differently when the == operator is used and when .equals is called.

Doesn't this implicitly violate the equals contract ?

  *  It is reflexive: for any non-null reference value
  *     x, x.equals(x) should return
  *     true.

EDIT:

Thanks for the fast answers. I figured that it is boxed differently, the real question is: why is it boxed differently ? I mean that this would be more intuitive if d == 0d than d.equals(0d) is intuitive and expected, however if d == 0 which looks like an Integer is true than 'intuitively' d.equals(0) should also be true.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

酷到爆炸 2024-10-28 08:10:22

只需将其更改为

System.out.println(d.equals(0d)); // is false ?! now true

You were Comparison double with Integer 0

Under the cover

System.out.println(d.equals(0)); // is false ?!

0 will be autoboxed to Integer and an Integer 的实例将被传递给 Double 类的 equals() 方法,在该方法中它将进行比较,

@Override
    public boolean equals(Object object) {
        return (object == this)
                || (object instanceof Double)
                && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
    }

当然会返回 false 。

更新

当您使用 == 进行比较时,它会比较值,因此不需要 autobox ,它直接对值进行操作。其中 equals() 接受 Object 因此,如果您尝试调用 d1.equals(0) ,则 0 不会对象,因此它将执行自动装箱并将其打包为作为对象的 Integer。

just change it to

System.out.println(d.equals(0d)); // is false ?! now true

You were comparing double with Integer 0

Under the cover

System.out.println(d.equals(0)); // is false ?!

0 will be autoboxed to Integer and an instance of Integer will be passed to equals() method of Double class, where it will compare like

@Override
    public boolean equals(Object object) {
        return (object == this)
                || (object instanceof Double)
                && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
    }

which is going to return false of course.

Update

when you do comparison using == it compares values so there is no need to autobox , it directly operates on value. Where equals() accepts Object so if you try to invoke d1.equals(0) , 0 is not Object so it will perform autoboxing and it will pack it to Integer which is an Object.

山色无中 2024-10-28 08:10:22

Number 对象仅等于具有相同值的数字(如果它们属于相同类型)。即:

new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));

和 类似的组合都是假的。

在您的情况下,文字 0 被装箱到 Integer 对象中。

Number objects only equal to numbers with the same value if they are of the same type. That is:

new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));

and similar combinations are all false.

In your case, the literal 0 is boxed into an Integer object.

飘然心甜 2024-10-28 08:10:22

可能值得注意的是,您应该像这样比较浮点数:

|x - y| < ε, ε very small

It's probably worth noting that you should compare floating point numbers like this:

|x - y| < ε, ε very small
十级心震 2024-10-28 08:10:22

d.equals(0)0 是一个 intDouble.equals() 代码仅对 Double 对象返回 true。

d.equals(0) : 0 is an int. The Double.equals() code will return true only for Double objects.

浅笑依然 2024-10-28 08:10:22

当您执行

d == 0

此操作时,会向上转型

d == 0.0

,但是没有自动装箱的向上转型规则,即使有 equals(Object) 也不会给出您想要的 Double 而不是 Integer 的命中。

When you perform

d == 0

this is upcast to

d == 0.0

however there are no upcasting rules for autoboxing and even if there were equals(Object) gives no hits that you want a Double instead of an Integer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文