如何生成唯一的哈希码?

8 浏览
0 Comments

如何生成唯一的哈希码?

此问题已有答案

覆盖 GetHashCode 的最佳算法是什么?

我有一个结构体,覆盖了一些函数和操作,但这不是很重要。

public struct Vector3
{
    public float X, Y, Z;
}

我正在通过哈希表过滤这些结构体的集合,它工作得很好。但我想验证只删除了重复项。默认情况下,我的IDE为 GetHashCode() 方法给了我这段代码:

public override int GetHashCode()
{
    var hashCode = -307843816;
    hashCode = hashCode * -1521134295 + X.GetHashCode();
    hashCode = hashCode * -1521134295 + Y.GetHashCode();
    hashCode = hashCode * -1521134295 + Z.GetHashCode();
    return hashCode;
}

这看起来对我来说很可疑。我十分确信,仅靠因子就会在 INT_32 上生成溢出。此外,我困惑于三个浮点数似乎都有相同的“权重”(-1521134295)。而且我不太确定浮点数的 GetHashCode() 做了什么。它的位模式本身应该已经是唯一的了。

从 96 位的输入中创建一个唯一的 32 位模式是不可能的。

那它是如何工作的呢?

  • HashMap 在删除具有相同 HashCode 的项之前是否使用 equal 方法。
  • 我只是幸运吗?
  • 这些数字我的 IDE 生成的“权重”和起始值是什么?

附:对于那些感兴趣的人,这个结构体的代码在这里。

public struct Vector3
{
    public float X, Y, Z;
    public Vector3(float x, float y, float z)
    {
        X = x;
        Y = y;
        Z = z;
    }     
    public static bool operator ==(Vector3 a, Vector3 b)
    {
        return (a.X == b.X && a.Y == b.Y && a.Z == b.Z);
    }
    public static bool operator !=(Vector3 a, Vector3 b)
    {
        return (a.X != b.X || a.Y != b.Y || a.Z != b.Z);
    }
    public static Vector3 operator +(Vector3 a, Vector3 b)
    {
        return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
    }
    public static Vector3 operator -(Vector3 a, Vector3 b)
    {
        return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
    }
    public float Magnitued
    {
        get
        {
            return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
        }
        private set { }
    }
    public Vector3 Normalized
    {
        get
        {
            var mag = Magnitued;
            return new Vector3(X / mag, Y / mag, Z / mag);
        }
        private set { }
    }
    public override bool Equals(object obj)
    {
        if (!(obj is Vector3))
        {
            return false;
        }
        var vector = (Vector3)obj;
        return X == vector.X && Y == vector.Y && Z == vector.Z;
    }
    public override int GetHashCode()
    {
        var hashCode = -307843816;
        hashCode = hashCode * -1521134295 + X.GetHashCode();
        hashCode = hashCode * -1521134295 + Y.GetHashCode();
        hashCode = hashCode * -1521134295 + Z.GetHashCode();
        return hashCode;
    }
}

admin 更改状态以发布 2023年5月24日
0
0 Comments

我认为你在这里有一个误解。哈希码不应该是唯一的,因为正如你所观察到的那样,有时是不可能的。

主要要求是被认为“相等”的对象应该具有相同的哈希码。

如果满足要求,引起溢出是可以的。

这也在文档中声明:

相等的两个对象返回相等的哈希码。然而,反过来说不成立:相等的哈希码不意味着对象相等,因为不同(不相等)的对象可以具有相同的哈希码。

你还可以在链接的页面上看到其他实现GetHashCode的方法。

0