1

这是针对二进制和原始专家的。我正在实现一个浮点 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 个不同坐标的相等性。

我正在考虑从三个浮点坐标中提取字节并使用每个坐标中的中间两个。

(以下不是代码,但堆栈溢出不会让我发布它,除非我缩进它)

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 方法的向量的哈希码总是相同......如果有人有一个非常低成本计算的好主意,我我很想听。或者,如果您可以将我引导到一个更深入地讨论如何存储浮点数以及如果上述比较方法返回相等的字节将始终相同的地方。

我可能需要一种新的比较方法而不是哈希函数,因为我真的无法确定任何字节都会匹配我猜...

4

1 回答 1

1

好吧,基本的想法很简单——你必须人为地降低你的浮点数的精度。如何有效地做到这一点在很大程度上取决于您期望看到的数据类型。

例如,如果您主要使用较小的值,则可以简单地使用如下内容:

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

请注意,虽然我实际上并没有满足您的if (e < .00001f && e > -.00001f)条件,但这没关系 - 想法是减少冲突,并确保相等的值将具有相等的哈希码。没有必要(或不可能)确保不相等的值不会具有相等的哈希码。其余的应该在 等的覆盖中处理Equals-==这就是必须存在严格相等检查的地方。与Equals公司不同,它GetHashCode() 只有关于单个向量的数据,因此您甚至无法选择使用来自多个单个向量的数据。

哈希码只是为了使密钥冲突不常见。Dictionary如果您的每个向量都返回0,那么仍然可以工作GetHashCode()- 只是性能会受到影响。只要相等的向量以相等的哈希码结束,哈希码就可以是任何适合您需要的东西:)

当然,最好的方法就是不使用向量作为字典中的键。找到您感兴趣的向量部分(对您最有帮助),并将其用作键。也许你会发现Dictionary这实际上并不是你想要的(例如,在游戏中,有大量不同的空间分区方法可以与向量一起使用——从简单的网格状布局,到手动空间分区,直到BSP 之类的东西)。

于 2014-07-16T06:53:16.670 回答