简体   繁体   English

确保GetHashCode()重载对于半相等的R3浮点向量返回相同的方法

[英]Method to ensure GetHashCode() overload returns the same for semi-equal R3 float vectors

This one is for the binary and primitive experts. 这是给二进制和原始专家的。 I am implementing a float R3 vector struct and my definition for "equality" is actually "mostly equal." 我正在实现一个float R3向量结构,而我对“等于”的定义实际上是“几乎相等”。 Specifically, for all coords of the compared vectors Abs( (a[i] - b[i]) / (a[i] + b[i]) ) < .00001 returns true. 具体来说,对于比较向量的所有坐标,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;
            }
        }
    }

My problem is in determining if there's a way to get the hash values to come out the same on vectors that meet this requirement due to the fact that I want to be able to use these vectors as "keys" for a Dictionary. 我的问题是,由于我希望能够将这些向量用作字典的“键”,因此确定是否有一种方法可以使散列值在满足此要求的向量上相同。

As you can see, the above code is used to check for equality on 3 different coordinates. 如您所见,以上代码用于检查3个不同坐标上的相等性。

I was thinking of extracting the bytes from the three float coordinates and using the middle two from each. 我正在考虑从三个浮点坐标中提取字节,并从每个中间使用中间两个。

(the following isn't code but Stack Overflow won't let me post it unless I indent it) (以下不是代码,但除非缩进,否则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}

Or something like that... In short - I'm curious how to ensure that the hashcodes of vectors which fit my equals method will always come out the same... If someone has a great idea with very low cost computation, I'd love to hear it. 或类似的东西...简而言之-我很好奇如何确保适合我equals方法的向量的哈希码总是相同的...如果某人对低成本的计算有很好的主意,我会d喜欢听到它。 Or if you could direct me to a place that discusses more in depth how floats are stored and which bytes will always be the same if the above comparison method returns equal. 或者,如果您可以将我引导到一个更深入地讨论浮点数存储方式的地方,并且如果上述比较方法返回相等的话,哪些字节将始终相同。

I may need a new comparison method rather than a hash function because there's really no way that I can be sure that any of the bytes will match I guess... 我可能需要一种新的比较方法而不是哈希函数,因为实际上我无法确定任何字节都可以匹配我猜...

Well, the basic idea is simple - you have to artificially reduce the precision of your floats. 好吧,基本思想很简单-您必须人为地降低浮标的精度。 How to do this efficiently depends a lot on the kind of data you're expecting to see. 如何有效地做到这一点在很大程度上取决于您期望看到的数据类型。

For example, if you're mostly using small values, you could simply use something like this: 例如,如果您主要使用较小的值,则可以使用类似以下的内容:

(int)Math.Round(x1 * 1000) 
^ (int)Math.Round(x2 * 1000) 
^ (int)Math.Round(x3 * 1000)

Note that while I'm not actually fulfilling your if (e < .00001f && e > -.00001f) condition, it doesn't matter - the idea is to reduce the collisions, and ensure that what values that are equal will have equal hash codes. 请注意,虽然我实际上并没有满足您的if (e < .00001f && e > -.00001f)条件,但这无关紧要-想法是减少冲突,并确保相等的值具有相等的值哈希码。 It's not necessary (or possible) to also ensure that values that are not equal will not have equal hash code. 不必(或不可能)也确保不相等的值不会具有相等的哈希码。 The rest should be handled in the overrides of Equals , == etc. - that's where strict equality checks must be present. 其余的应该在Equals==等的重写中进行处理-这是必须进行严格的相等性检查的地方。 Unlike Equals and company, GetHashCode() only has data about a single vector, so you don't even have an option of using data from more than that single vector in there. Equals和company不同, GetHashCode() 包含有关单个向量的数据,因此您甚至没有选择使用其中多个向量的数据。

Hash codes are only there to make key collisions infrequent. 哈希码仅用于使键冲突很少发生。 So Dictionary will still work if each of your vectors will return 0 in GetHashCode() - it's just that the performance will suffer. 因此,如果您的每个向量在GetHashCode()返回0Dictionary仍然可以使用-只是性能会受到影响。 As long as equal vectors end up with equal hash codes, the hash code can be anything that suits your needs :) 只要相等的向量以相等的哈希码结尾,则哈希码可以是满足您需求的任何东西:)

Of course, the best way would simply be not to use vectors as keys in the dictionary. 当然,最好的方法就是不将向量用作字典中的键。 Find the part of the vector that interests you (helps you the most), and use that as a key. 找到向量中您最感兴趣的部分(对您最大的帮助),并将其用作键。 Maybe you'll find out Dictionary isn't actually what you want anyway (for example, in a game, there's tons of different space partitioning methods that can be used with vectors - from simple grid-like layouts, through manual space partitioning, up to things like BSP). 也许您会发现Dictionary实际上并不是您真正想要的(例如,在游戏中,有大量可用于向量的不同空间分区方法-从简单的网格状布局到手动空间分区,直至(例如BSP)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM