Equals 方法中浮点/双精度实例变量的相等比较是否应该准确?

2023-12-02

我正在重写对象的相等方法。假设里程表中的 km 变量存储为双精度型(以及一些对于示例而言并不重要的其他变量)。

public class Odometer { 
    private double km;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;
        temp = Double.doubleToLongBits(km);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Odometer other = (Odometer) obj;
        if (Double.doubleToLongBits(km) != Double.doubleToLongBits(other.km))
            return false;
        return true;
    }
}

现在,Eclipse 生成的 double 变量(以及哈希码)的比较是精确的按位比较。但是,我被告知在比较浮点值或双精度值时要使用“epsilon”差异。我什至听说过这样的说法:“比较浮点数时切勿使用相等性”。

boolean equals(double x, double y, double epsilon) { 
    return x - y < epsilon;
}

JUnitassertEquals双打的方法证明了这一点:

assertEquals(double expected, double actual, double epsilon)

那么,我应该在这里使用哪个比较呢?


Javadoc 的equals方法说明(强调我的):

https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-

equals 方法在非空对象引用上实现等价关系:

  • 它是自反的:对于任何非空引用值 x,x.equals(x) 应该返回 true。
  • 它是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
  • 它是传递性的:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,则 x.equals(z) 应返回 true。
  • 它是一致的:对于任何非空引用值 x 和 y,如果对象的 equals 比较中使用的信息没有被修改,则多次调用 x.equals(y) 一致返回 true 或一致返回 false。
  • 对于任何非空引用值 x,x.equals(null) 应返回 false。

相等方法必须是传递的。如果您使用了 epsilon,则这将不成立。

考虑双精度值 x = 2.0、y = 2.6、z = 3.1 和 epsilon = 1.0。

请注意,z - y = 0.5 和 y - x = 0.6,两者都小于 epsilon 1.0。然而,z - x = 1.1,即more比1.0。

因此,我们会有“x 等于 y”和“y 等于 z”,但没有“x 等于 z”,这会破坏传递性。如果这些是某些其他对象的实例变量(例如上面示例中的里程表),也会发生同样的情况。

因此,相等应该是精确的。如上所述转换为位,就像使用一样Double.compare(double d1, double d2)或将它们转换为 Double 值,然后使用Double.compareTo(Double anotherDouble)。请注意,它们会将 0.0 和 -0.0 视为不同的数字。

https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#compare-double-double- https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#compareTo-java.lang.Double-

这对于保持哈希函数的一致性也很重要。

不要使用内置的 Java 相等运算符==即使对于原始双精度值也是如此。正如 JavaDocs 中所述compareTo方法,相等失败NaN。 (这个 StackOverflow 问题还有更多信息:为什么Java的Double.compare(double, double)是这样实现的?)

最后一点 - 这不适用于上面的示例,因为使用了原始双精度值,但是如果您使用Double对象,记得检查null在尝试将它们传递到任何 Double 比较函数之前。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Equals 方法中浮点/双精度实例变量的相等比较是否应该准确? 的相关文章

随机推荐

  • 如何用PHP下载大文件?

    我花了一周的时间来找到这个问题的正确答案 Right 我的意思是绝对符合现有的网络标准 可靠且性能有效 最后 我找到了解决方案 我在 StackOverflow 上找到的所有内容 在 PHP 中可靠地下载大文件 如何通过PHP脚本下载大文件
  • 使用 Quartz.NET 3.0.3 和简单注入器进行构造函数注入操作方法

    我正在尝试在 Windows 服务中使用 Quartz Net v3 0 3 和简单注入器 我有一个作业类 我想在其下面注入一些依赖项 例如我的记录器 public class JobWorker IJob private ILogger
  • 向按钮添加彩色阴影

    我需要向具有 来自 zeplin 这些属性的按钮添加阴影 这就是设计 我试过这段代码
  • React 中生成器的调用次数超出预期

    我发现生成器似乎被调用两次的行为 下面是一个简单的代码 它从生成器获取一个数字并将其输出到控制台 它期望控制台输出 0 和 1 但实际上输出的是 0 和 2 import useState useEffect from react func
  • <%= 导轨 4 中有一个块

    我正在尝试在助手中使用块 但这给了我这个错误 SyntaxError syntax error unexpected rbout concat green title do to s erbout concat n erb 4254 syn
  • 大多数静态数据流的 CRC 计算

    背景 我有一段内存 1024字节 最后 1020 字节始终相同 前 4 个字节将发生变化 产品的序列号 我需要计算CRC 16 CCITT 0xFFFF 起始 0x1021 掩码 对于整个内存部分 CRC WHOLE 问题 是否可以仅计算前
  • 如何在 XAML 中绑定到静态属性?

    我试图将不同类的静态属性绑定到 TextBlock 的 Text 属性 并且可以使绑定正常工作 但是当静态属性的值发生更改时 Text 属性不会更新 我读过 我无法使用 INotifyPropertyChanged 因为该属性是静态的 并且
  • 导航推送新的根控制器

    我正在尝试将新的根控制器推送到导航堆栈 但使用侧面显示菜单 我的应用程序委托具有以下内容 welcomeViewController MyWelcomeViewController alloc initWithNibName MyWelco
  • ORACLE 中的利斯塔格

    我正在尝试使用 LISTAGG 来获取两列以上 SELECT deptname deptno LISTAGG ename WITHIN GROUP ORDER BY ename AS employees FROM emp GROUP BY
  • 在 $0 和 BASH_SOURCE 之间选择

    一个人如何选择 0 and BASH SOURCE 0 这段描述来自GNU对我帮助不大 BASH SOURCE An array variable whose members are the source filenames where t
  • 在 OCaml 中组合一列列表

    我想在 OCaml 中转置一个矩阵 不使用递归或任何类型的循环 例如 如果我有以下矩阵 1 2 3 4 我想要的输出 1 3 2 4 到目前为止我所做的是将原始矩阵分解为单独的列 function that separates into c
  • HTML5 是否使 Javascript 游戏更安全(更安全)?

    我知道 JavaScript 是一种极其不安全的持久游戏编程方式 例如 您在 RPG 中进行战斗计算 然后在获胜时通过链接到 PHP 页面来奖励 XP 该页面会将 XP 添加到数据库中 因为玩家可以制作自己的 javascript 来始终获
  • WPF 树数据模板取决于项目类型

    我有一个 MVVM WPF 应用程序 其中有一棵包含自引用数据的树 该数据通过分层转换器绑定到该树 如示例 http www telerik com help wpf radtreeview how to bind to self refe
  • Android WebView 与layer_type_software 不显示HTML5 画布内容

    自上次更新 Android WebView 以来 通过将 WebView 的图层类型设置为 View LAYER TYPE SOFTWARE 来禁用硬件加速时 带有 HTML5 画布的网页无法正确显示 这个问题有解决方法吗 当我省略以下 J
  • 构建 VSCode 和 Android Studio (Flutter) 的 gradle 时配置根项目“android”时出现问题

    今天开始学习Flutter 并成功下载了所有东西 但是当我运行我的应用程序时 调试器 两者VSCode and Android Studio 给我这个错误 Launching lib main dart on sdk gphone x86
  • 如何动态修改函数的本地命名空间?

    注意 这个问题假设 Python 2 7 3 我正在寻找一种合理的方法来动态修改函数的本地命名空间 最好以一种给函数体函数添加最少混乱的方式 我的想法是这样的 import os from namespace updater import
  • ggplot2时间序列数据在R中显示不稳定的线

    我想从此链接重现此图像 但我得到了这个奇怪的结果 这相当简单 我想从数据框中绘制时间序列 它不是 xts 类型的数据 这只是一个简单的数据框 日期已被识别为日期 不确定 为什么 ggplot 显示这种不稳定的线条而不是 geom line
  • 如何等待元素包含属性 style="display:none;"使用 Selenium 和 Python

    使用 Selenium Python 时 我需要等待 暂停直到 style display none 显示为 div div div gt 单击按钮后 将显示以下内容 加载中 div class notification info styl
  • 使用enable_if检查成员是否存在

    这就是我想做的 template
  • Equals 方法中浮点/双精度实例变量的相等比较是否应该准确?

    我正在重写对象的相等方法 假设里程表中的 km 变量存储为双精度型 以及一些对于示例而言并不重要的其他变量 public class Odometer private double km Override public int hashCo