为了账号安全,请及时绑定邮箱和手机立即绑定

在 equals() 方法中比较双精度的正确方法

在 equals() 方法中比较双精度的正确方法

慕容3067478 2023-09-13 10:51:23
我的类中有双精度类型,并且必须重写 equals()/hashCode()。所以我需要比较双精度值。哪个是正确的方法?版本1:boolean isEqual(double a, double b){    return Double.doubleToLongBits(a) == Double.doubleToLongBits(b);}版本2:boolean isEqual(double a, double b){    final double THRESHOLD = .0001;    return Math.abs(a - b) < THRESHOLD;}double或者我应该完全避免原始并使用它的包装类型Double?这样我就可以使用Objects.equals(a,b), ifa和bare Double 。
查看完整描述

2 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

在 equals/hashcode 方法中推荐使用的方法[需要引用]是分别使用Double.doubleToLongBits()Double.hashcode()

这是因为如果哈希码不同,则 equals 合约要求两个输入的计算结果为“不同”。反之则没有限制。

(注意:事实证明Double.compare()内部使用,doubleToLongBits()但 API 没有指定。因此我不会推荐它。另一方面,hashCode() 确实指定它使用doubleToLongBits()。)

实际例子:

@Override

public boolean equals(Object obj) {

    if (obj == null || getClass() != obj.getClass())

        return false;


    Vector2d other = (Vector2d)obj;

    return Double.doubleToLongBits(x) == Double.doubleToLongBits(other.x) &&

           Double.doubleToLongBits(y) == Double.doubleToLongBits(other.y);

}


@Override

public int hashCode() {

    int hash = 0x811C9DC5;

    hash ^= Double.hashCode(x);

    hash *= 0x01000193;

    hash ^= Double.hashCode(y);

    hash *= 0x01000193;

    return hash;

}


查看完整回答
反对 回复 2023-09-13
?
DIEA

TA贡献1820条经验 获得超2个赞

double不应该用作建立对象相等性及其hashcode的组件。

这是因为浮点数存在固有的不精确性,并且人为地双饱和+/-Infinity

为了说明这个问题:

System.out.println(Double.compare(0.1d + 0.2d, 0.3d));
System.out.println(Double.compare(Math.pow(3e27d, 127d), 17e256d / 7e-128d));

印刷:

1
0

...这转化为以下两个错误陈述

0.1+0.2>0.3

(3 * 1027)127 == 17 * 10256 / (7 * 10-128)

因此,你的软件会让你对两个不相等的相等数字或两个非常大或非常小的不相等数字相等采取行动。


查看完整回答
反对 回复 2023-09-13
  • 2 回答
  • 0 关注
  • 91 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信