哈希码实现双精度

本文关键字:双精度 实现 哈希码 | 更新日期: 2023-09-27 17:50:32

我以前问过一个关于这门课的问题,但这里又有一个。

我创建了一个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;
    }

这个是成立的,当虚部和实部非常接近时,它说它们是相同的。

现在我正在尝试实现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()的契约(它不是传递的,首先),所以Hashtable一起使用将无法工作,无论你如何实现GetHashCode()

对于这种事情,你真的需要一个空间索引,比如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().

我将创建只读属性,将实数和虚数四舍五入到最接近的十万分之一,然后在这些getter属性上执行等号和哈希码实现。