【问题标题】:simple == instead of doubleToLongBits [duplicate]简单 == 而不是 doubleToLongBits [重复]
【发布时间】:2019-10-03 19:55:09
【问题描述】:

我有两个双精度值(原始类型和非对象!),当我让 Eclipse 为这些双精度值生成 equals/hashCode 时,它将像这样覆盖它:

@Override
public boolean equals(Object obj) {
...
return Double.doubleToLongBits(mydouble) == Double.doubleToLongBits(obj.mydouble) && ..;

}

所以它使用doubleToLongBits 来比较是否相等。但是,当使用 doubleToLongBits 时,0!=-0 的比较返回 false。为什么在equals-方法中需要这个?

我的问题:为什么 Eclipse 不简单地使用

 @Override
 public boolean equals(Object obj) {
 ..
 return mydouble == obj.mydouble && ..;
 }

比较是否相等?这会是错的吗?

问题是特定于原始类型的,以及为什么人们应该使用原始类型而不是简单地使用 doubleToLongBits,例如0.1 == 0.1.

【问题讨论】:

  • 如果“mydouble”是一个对象(例如“Double”)而不是一个原始的(“double”)......那确实是错误的。问:您是否期望与 0.0 != -0.0 不同?
  • @paulsm4 不,我的 double 是原始类型。
  • 我建议你了解更多关于浮点数的知识。它们本质上是您尝试表示的数字的不精确近似值。如果双精度值是某些计算的结果,这尤其是一个问题。请参阅stackoverflow.com/questions/588004/… 讨论这是如何造成问题的。
  • @NathanHughes 我知道,但是,==Double.compare(x,y) 的存在是有原因的..
  • 还请考虑,对于普通的==,包含 NaN 作为某些字段值的对象永远不会等于其他任何东西,甚至它本身。如果你把它放到一个集合中,这个集合就会对它撒谎并声称它不包含那个东西。

标签: java double


【解决方案1】:

回答“为什么 Eclipse 使用 doubleToLongBits”?

这是代码生成功能。 Eclipse 不知道上下文。它只是试图咕哝出一些基本没问题的东西。如果它生成类似this.d == that.d 的东西,它将触发各种静态分析工具,这些工具会将这条线标记为比较两个双精度数(因为它们有类似this one 的规则)。相反,它比较 long 并且静态分析工具很高兴,因为它们很愚蠢(对很多事情有用,但很容易被愚弄)。

如果您使用双精度,则存在一定的公差,在此范围内区分两个值是没有用的。在这方面,这些替代方案中的任何一个都没有比另一个更能帮助您。这只是静态分析工具触发次数多于其他的一次。

通常,当您创建一个 equals 方法时,它是针对某个域对象的。 equals 和 hashcode 方法不必考虑对象上的所有字段,很多时候它们使用称为业务键的子集来唯一地标识对象。您可能根本不需要在 equals 或 hashCode 方法中包含此字段。同样,代码生成器没有上下文可以继续,并且将提供一种方法来包含所有字段,无论它是否有意义。

【讨论】:

  • 这对我有帮助,谢谢!因此,将原始双精度值与this.d == that.d 而不是doubleToLongBits 进行比较是不会错误的。因为有了这个,0==-0 将返回 true,这就是我想要的。然而,正如你所说的business key..这是一个好点。谢谢!
【解决方案2】:

这样做是因为它遵循 Double.compare() 实现 - 所以它与 Java 默认提供的一致:

public static int compare(double d1, double d2) { //Java 12 implementation
    if (d1 < d2)
        return -1;           // Neither val is NaN, thisVal is smaller
    if (d1 > d2)
        return 1;            // Neither val is NaN, thisVal is larger

    // Cannot use doubleToRawLongBits because of possibility of NaNs.
    long thisBits    = Double.doubleToLongBits(d1);
    long anotherBits = Double.doubleToLongBits(d2);

    return (thisBits == anotherBits ?  0 : // Values are equal
            (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
             1));                          // (0.0, -0.0) or (NaN, !NaN)
}

编辑:也等于同一类

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

【讨论】:

  • 我知道 Double.compare 可以在后台使用 doubleToLongBits。那不是问题。问题是:我为什么要使用它而不是原始的“==”
猜你喜欢
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2021-06-17
  • 2018-03-29
  • 1970-01-01
  • 2013-03-31
  • 2020-06-05
相关资源
最近更新 更多