Hashcode实现双精度

我之前已经问了一个关于这个课程的问题,但这里又是一个问题。

我创建了一个Complex类:

public class Complex { public double Real { get; set; } public double Imaginary { get; set; } } 

我正在实现EqualsHashcode函数,而Equal函数考虑了一定的精度。 我使用以下逻辑:

  public override bool Equals(object obj) { //Some default null checkint etc here, the next code is all that matters. return Math.Abs(complex.Imaginary - Imaginary) <= 0.00001 && Math.Abs(complex.Real - Real) <= 0.00001; } 

这很有用,当Imaginary和Real部分彼此非常接近时,它说它们是相同的。

现在我正在尝试实现HashCode函数,我已经使用了一些John skeet在这里使用的示例,目前我有以下内容。

  public override int GetHashCode() { var hash = 17; hash = hash*23 + Real.GetHashCode(); hash = hash*23 + Imaginary.GetHashCode(); return hash; } 

但是,这并没有考虑我想要使用的特定精度。 所以基本上是以下两个类:

Complex1[Real = 1.123456; Imaginary = 1.123456]

Complex2[Real = 1.123457; Imaginary = 1.123457]

Equal但不提供相同的HashCode ,我该如何实现?

首先,您的Equals()实现已被破坏。 请阅读此处以了解原因。

其次,这样的“模糊等于”打破了Equals()的契约(它不是传递性的,一方面),所以无论你如何实现GetHashCode()将它与Hashtable一起使用都行不通

对于这种事情,你真的需要一个空间索引,比如R-Tree 。

在计算哈希值时只需删除精度。

 public override int GetHashCode() { var hash = 17; hash = hash*23 + Math.Round(Real, 5).GetHashCode(); hash = hash*23 + Math.Round(Imaginary, 5).GetHashCode(); return hash; } 

其中5是精确值

我看到两个简单的选择:

  • 使用十进制而不是双精度
  • 而不是使用Real.GetHashCode,使用Real.RoundTo6Ciphers()。GetHashCode()。

然后你将拥有相同的哈希码。

我将创建只读属性,将Real和Imaginary舍入到最接近的千分之一,然后在这些getter属性上执行equals和hashcode实现。