[英]What are the rules I should follow to ensure GetHashCode() method returns unique value for an object?
[英]Method to ensure GetHashCode() overload returns the same for semi-equal R3 float vectors
這是給二進制和原始專家的。 我正在實現一個float R3向量結構,而我對“等於”的定義實際上是“幾乎相等”。 具體來說,對於比較向量的所有坐標,Abs((a [i]-b [i])/(a [i] + b [i]))<.00001返回true。
private static bool FloatEquality(float a, float b)
{
if (a == b)
{
return true;
}
else
{
float e;
try
{
e = (b - a) / (b + a);
}
catch (DivideByZeroException)
{
float g = float.Epsilon;
e = (b - a) / g;
}
//AppConsole.AppConsole.Instance.WriteLine(e);
if (e < .00001f && e > -.00001f)
{
return true;
}
else
{
return false;
}
}
}
我的問題是,由於我希望能夠將這些向量用作字典的“鍵”,因此確定是否有一種方法可以使散列值在滿足此要求的向量上相同。
如您所見,以上代碼用於檢查3個不同坐標上的相等性。
我正在考慮從三個浮點坐標中提取字節,並從每個中間使用中間兩個。
(以下不是代碼,但除非縮進,否則Stack Overflow不會讓我發布它)
Vector(x,y,z):
x's float byte[] = [ x1 x2 x3 x3 ]
y's float byte[] = [ y1 y2 y3 y4 ]
z's float byte[] = [ z1 z2 z3 z4 ]
Hash code: byte[] {x2^x3 , y2^y3, z2 ^ z3, x2 ^ z3}
或類似的東西...簡而言之-我很好奇如何確保適合我equals方法的向量的哈希碼總是相同的...如果某人對低成本的計算有很好的主意,我會d喜歡聽到它。 或者,如果您可以將我引導到一個更深入地討論浮點數存儲方式的地方,並且如果上述比較方法返回相等的話,哪些字節將始終相同。
我可能需要一種新的比較方法而不是哈希函數,因為實際上我無法確定任何字節都可以匹配我猜...
好吧,基本思想很簡單-您必須人為地降低浮標的精度。 如何有效地做到這一點在很大程度上取決於您期望看到的數據類型。
例如,如果您主要使用較小的值,則可以使用類似以下的內容:
(int)Math.Round(x1 * 1000)
^ (int)Math.Round(x2 * 1000)
^ (int)Math.Round(x3 * 1000)
請注意,雖然我實際上並沒有滿足您的if (e < .00001f && e > -.00001f)
條件,但這無關緊要-想法是減少沖突,並確保相等的值具有相等的值哈希碼。 不必(或不可能)也確保不相等的值不會具有相等的哈希碼。 其余的應該在Equals
, ==
等的重寫中進行處理-這是必須進行嚴格的相等性檢查的地方。 與Equals
和company不同, GetHashCode()
僅包含有關單個向量的數據,因此您甚至沒有選擇使用其中多個向量的數據。
哈希碼僅用於使鍵沖突很少發生。 因此,如果您的每個向量在GetHashCode()
返回0
, Dictionary
仍然可以使用-只是性能會受到影響。 只要相等的向量以相等的哈希碼結尾,則哈希碼可以是滿足您需求的任何東西:)
當然,最好的方法就是不將向量用作字典中的鍵。 找到向量中您最感興趣的部分(對您最大的幫助),並將其用作鍵。 也許您會發現Dictionary
實際上並不是您真正想要的(例如,在游戲中,有大量可用於向量的不同空間分區方法-從簡單的網格狀布局到手動空間分區,直至(例如BSP)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.