哈希码实现双精度
本文关键字:双精度 实现 哈希码 | 更新日期: 2023-09-27 17:50:32
我以前问过一个关于这门课的问题,但这里又有一个。
我创建了一个Complex类:
public class Complex
{
public double Real { get; set; }
public double Imaginary { get; set; }
}
我实现了Equals
和Hashcode
函数,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属性上执行等号和哈希码实现。