IEquatable 在容差范围内,如何实现 GetHashCode() [重复]

2024-01-07

我有一个Point3d实现的结构体IEquatable<Point3d>通过以下方式:

public override bool Equals(object obj) {
    return obj is Point3d p && Equals(p);
}

public bool Equals(Point3d other) {
    return Equals(other, Tolerance.ToleranceDecimal);
}

public bool Equals(Point3d other, double tolerance) {
    if (tolerance < 0) throw new ArgumentOutOfRangeException(nameof(tolerance), tolerance, "Expected a tolerance greater than or equal to 0");
    return Math.Abs(X - other.X) <= tolerance && Math.Abs(Y - other.Y) <= tolerance && Math.Abs(Z - other.Z) <= tolerance;
}

public override int GetHashCode() {
    var hash = 17;
    hash = hash * 23 + X.GetHashCode();
    hash = hash * 23 + Y.GetHashCode();
    hash = hash * 23 + Z.GetHashCode();
    return hash;
}

public static bool operator ==(Point3d firstPoint, Point3d secondPoint) {
    return firstPoint.Equals(secondPoint);
}

public static bool operator !=(Point3d firstPoint, Point3d secondPoint) {
    return !(firstPoint == secondPoint);
}

这已经在应用程序中大量使用,期望检查两点之间的相等性以允许容差(这是实现正常工作所必需的)。

如果我注意到Equals and GetHashCode方法不一致,确实无法写GetHashCode以能够产生良好且一致结果的形式。在使用 Linq 查询的情况下,此问题尤其成问题,例如points.Distinct()因为如果直接比较,结果点可能会被认为是相等的,例如points[0] == points[1]

我个人认为最好的选择是改变Equals如下,使其行为与GetHashCode:

public bool Equals(Point3d other) {
    return Equals(other, 0);
}

然而,由于这已经在应用程序中大量使用,这将是一个重大的突破性变化。我认为这样做是错误的,但我正在考虑改变GetHashCode to:

public override int GetHashCode() {
    return 0;
}

我的理解是,上述内容将迫使Equals使用的方法会导致性能下降,但也允许在 Linq 查询中将容差内的点视为相等。我想知道这是否会让我陷入任何其他潜在的陷阱。

我不确定还有哪些其他途径可供我使用,因此我非常寻求有关解决此问题的最佳方法的建议。

提前致谢!


痛苦的事实是你can't实施正确Equals与任意tolerance. Equals (see https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx欲了解详情)必须 是及物的 i.e. (x.Equals(y) && y.Equals(z))回报true 当且仅当 x.Equals(z)回报true.

在这里我们可以创建一个反例对于给定的Tolerance.ToleranceDecimal:

 Point3d x = new Point3d(-Tolerance.ToleranceDecimal * 2.0 / 3.0, 0, 0);
 Point3d y = new Point3d(0, 0, 0);
 Point3d z = new Point3d(Tolerance.ToleranceDecimal * 2.0 / 3.0, 0, 0);

如你看到的

 x.Equals(y) == true
 y.Equals(z) == true

But

 x.Equals(z) == false

Since Equals实现不正确,我们无法创建相应的GetHashCode, 除了退化的 (and useless)

 public override int GetHashCode() {
   return 0;
 }

because GetHashCode必须返回same价值x and y if x.Equals(y) == true。在我们的例子中:让x < y and y = x + N * tolerance

 x equals to 
 x + tolerance / 2.0 equals to
 x + tolerance / 2.0 * 2 equals to
 x + tolerance / 2.0 * 3 equals to
 ...
 x + tolerance / 2.0 * 2 * N equals to
 y

这意味着对于任意任意x and y和非零容忍GetHashCode必须为任何参数返回相同的值。

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

IEquatable 在容差范围内,如何实现 GetHashCode() [重复] 的相关文章

随机推荐

  • 如何为自定义 Java 标记添加 Eclipse 快速修复?

    我想向 Eclipse 的问题视图报告 Java 文件的自定义问题并为它们提供快速修复 标准方法是使用扩展点org eclipse core resources markers声明自定义标记并通过调用添加标记org eclipse core
  • 在 VS 设计器中加载包时禁用 SSIS 包验证

    我有一些部署到 SQL 2005 Server 的 SSIS 包 随后在 Visual Studio 2003 中设计和维护 当我打开任何 BIDS 项目以及其中一个包时 设计器总是验证每个数据流和任务目的 通常 这不是问题 但是 在某些情
  • Jasmine单元测试observable订阅不触发

    我将 Angular 5 与 Jasmine 和 Karma 一起使用 我正在尝试测试某个功能是否有效 但我的订阅在单元测试期间没有触发 这导致我的单元测试失败 因为我正在使用 jasmine 的 did 函数 我想让这个单元测试成功 我已
  • Tomcat 中的 NIO 连接器

    我试图通过配置 server xml 文件在 Tomcat 6 0 中启用 NIO 连接器 但我得到Firefox 无法与位于 localhost 8081 的服务器建立连接 每当我输入时在浏览器中本地主机 8081 这就是我在 Tomca
  • DataGridTextColumn - 如何绑定IsReadonly?

    在 Silverlight 4 中 DataGridTextColumn 的 IsReadOnly 属性似乎不是依赖属性 因此我无法将它绑定到视图模型上的属性 似乎唯一的选择是使用 DataTemplate 但即使在这里我也面临两个主要问题
  • 用循环填充矩阵

    我正在尝试创建一个矩阵n by k with kmvn 使用循环进行协变量 非常简单 但到目前为止还没有工作 这是我的代码 n 1000 k 5 p 100 mu 0 sigma 1 x matrix data NA nrow n ncol
  • 如何在 laravel eloquent 中添加两列值并执行 where 条件

    这是我的桌子 id remaining amount additional amount 1 200 0 2 100 100 3 300 100 4 200 50 我正在尝试获取总和为剩余数量 额外金额 gt 0 result this g
  • 响应 SwiftUI 中的按键事件

    我想响应按键 例如esc键在 macOS OSX 上 以及在 iPad 上使用外部键盘时 我怎样才能做到这一点 我想过用 available available与 SwiftUI 的onExitCommand https developer
  • 一行中没有所有 True 值的布尔数组

    I have numpy array np random seed 100 mask np random choice True False size 10 3 print mask True True False False False
  • 如何在 git url 的用户名或密码中转义“@”

    在命令行上推送到 git 的格式之一是 Url format https username password github com owner repo 我的挑战是用户名和密码 这是我无法控制的共享帐户 包含 在他们里面 实际上都是 在这种
  • Spring-Boot Jersey:允许 Jersey 提供静态内容

    该应用程序使用 JDK 8 Spring Boot 和 Spring Boot Jersey 启动器 并打包为 WAR 尽管它是通过 Spring Boot Maven 插件在本地运行 我想做的是将我动态 在构建时 生成的文档作为欢迎页面
  • 部分排列

    我有以下递归函数用于输出部分组合 void comb string sofar string rest int n string substring if n 0 cout lt lt sofar lt lt endl else for s
  • 使用 AutoSize 时的 FlowLayoutPanel 高度错误

    我有一个包含 1 列和 3 行的 TableLayout 的表单 其中包含 2 个 FlowLayoutPanel 和一个文本框 所有行均为 AutoSize 列设置为 Percentage 100 每个 FlowLayoutPanel 都
  • .NET Core 2.1 - 构建时的 dotnet/exe,缺少软件包

    我一直在一台机器上进行开发 最近尝试在另一台电脑上安装我的应用程序 我想我已经推断出自从在 NET Core 中以来就没有找到 nuget 包 nuget 将包放在本地 Users 文件夹路径中 我最初添加了
  • 从自定义表单将数据插入 WordPress 数据库表

    我正在尝试通过创建表将数据插入 Wordpress 数据库 我已经创建了表 但是当我尝试从表单插入数据时 它不会插入数据 我已经检查数据库连接是否有效 但插入没有发生 有人可以帮我解决这个问题吗 这是我的代码
  • C++ 继承和函数重写

    在C 中 基类的成员函数是否会被其同名的派生类函数覆盖 即使它的原型 参数的数量 类型和常量 不同 我想这是一个愚蠢的问题 因为许多网站都说函数原型应该相同才能发生这种情况 但为什么下面的代码不能编译 我相信这是一个非常简单的继承案例 in
  • 如何在不遍历链表的情况下统计链表中的节点数?

    面试时有人问我如何在不遍历链表的情况下统计链表中的节点数 有什么办法可以实现这一点吗 我能想到的唯一方法是添加一个节点数计数器 每次节点数都会增加add or insert方法被调用 并在以下情况时递减delete被调用 您无法对占用的内存
  • 为什么Android的frustumM生成的矩阵与Redbook的不同?

    Something seems funny about the way that Android s frustumM works If I check the OpenGL red book the matrix generated lo
  • Proguard 在 proguard-rules.pro 添加包名称后运行 R8 时检测到缺少类

    AGPBI将此作为输出 gt Task app minifyReleaseWithR8 AGPBI kind warning text Unexpected reference to missing service class META I
  • IEquatable 在容差范围内,如何实现 GetHashCode() [重复]

    这个问题在这里已经有答案了 我有一个Point3d实现的结构体IEquatable