众所周知,用==
比较浮点数通常是一个错误。我写道,在3D向量类中(具有浮点分量X,Y,Z),如果两个向量的距离被视为零,则它们被视为相等。
public override bool Equals(object obj)
{
if (obj == null) {
return false;
}
if (GetType () != obj.GetType ()) {
return false;
}
float d = DistSq ((Vec) obj);
return IsConsideredZero (d);
}
public float DistSq(Vec p)
{
Vec d = this - p;
return d.LengthSq ();
}
public float LengthSq()
{
return X * X + Y * Y + Z * Z;
}
private const float VEC_COMPARE_EPSILON_ABS = 1E-05f;
public static bool IsConsideredZero(float f)
{
return Math.Abs (f) < VEC_COMPARE_EPSILON_ABS;
}
到目前为止,一切正常。但是,现在我想获取向量的哈希码。我可以看到像hash = (int)X^(int)Y^(int)Z
这样的东西注定会失败。我能想到的最好的是:
public override int GetHashCode()
{
return 0;
}
当然,这很烂。有什么方法可以获取合理的哈希码吗? NaN和其他特殊值是可能的,但如果很重要的话,则不太可能。 最佳答案
假设您要具有普通的哈希码/等于属性是不可能的:
第一条规则是问题-因为如果每个值都被认为等于下一个更大的可表示数字“等于”,那么最终所有数字都相等。例如,假设一个数字等于0.1以内的数字:
0等于0.08
0.08等于0.16
0.16等于0.24
=> 0根据传递性规则等于0.16
=> 0根据传递性规则等于0.24
(等等)
如果您忽略传递性规则,那么您仍然(大概)希望“相等”的值具有相等的哈希码。这有效地执行了传递性规则-在上面的示例中,0和0.08必须具有相等的哈希码,而0和0.16则必须具有相等的哈希码。因此,0和0.16必须具有相等的哈希码,依此类推。因此,您将没有有用的哈希码-它必须是一个常量。
关于floating-point - 有没有办法用epsilon获取浮点数的哈希码?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/580905/