我正在为我的Vector类覆盖GetHashCode()
函数。它仅包含3个浮点数X
,Y
,Z
。我想知道什么是最好的方法。
public override int GetHashCode()
{
var sum = X + 3 * Y + 5 * Z;
return sum.GetHashCode();
}
我需要它来快速在一个大集合中找到一个Vector。
我不想只返回X.GetHashCode()
,因为这将导致对直线的相等检查过多。
当前实现的问题在于,如果浮点数很大,我可能会得到整数溢出。
有没有办法告诉我的编译器消除任何溢出?
有更好的解决方案吗?
谢谢。
答案 0 :(得分:3)
有没有办法告诉我的编译器消除任何溢出?
是的,您可以为此使用unchecked关键字。正如@kalimag指出的那样,只有整数值会在溢出时引发异常。
有更好的解决方案吗?
组合哈希值的正确方法是:
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
hash = hash * 23 + Z.GetHashCode();
return hash;
}
}
有关说明,请参见this question。
答案 1 :(得分:1)
通常,我们将哈希码与 xor (更好的解决方案)结合使用:
public override int GetHashCode() =>
X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
有关详情,请参见Why is XOR the default way to combine hashes?
xor 永远不会抛出任何异常
答案 2 :(得分:0)
当我不得不重写Equals
或GetHashCode
时,我通常认为我做错了。
我需要它来快速在一个大集合中找到一个Vector。
有更好的解决方案吗?
如果集合是Dictionary
,怎么办?
public class Vector
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
}
public class MyClass
{
private readonly Dictionary<(int x, int y, int z), Vector> _vectors = new Dictionary<(int x, int y, int z), Vector>();
public MyClass()
{
var vector1 = new Vector { X = 1, Y = 2, Z = 3 };
var vector2 = new Vector { X = 2, Y = 3, Z = 4 };
_vectors.Add((x: vector1.X, y: vector1.Y, z: vector1.Z), vector1);
_vectors.Add((vector2.X, vector2.Y, vector2.Z), vector2);
}
public Vector FindVector(int x, int y, int z)
{
return _vectors[(x, y, z)];
}
}