【问题标题】:How to generate a unique Hashcode? [duplicate]如何生成唯一的Hashcode? [复制]
【发布时间】:2019-01-11 07:44:15
【问题描述】:

所以,我有这个结构。它有一些函数和运算符被覆盖,但这并不重要。

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

我正在通过 HashTable 过滤这些集合,它工作正常。但我想验证是否只删除了重复项。默认情况下,我的 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。

  • 我只是幸运吗?

  • 我的 IDE 作为“权重”生成的这些数字是什么? 起始值?

PS:有兴趣的可以看结构体的代码。

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;
    }
}

【问题讨论】:

  • 请注意,由于其大小有限,散列不应是唯一的。见pigeonhole principle。良好的散列算法可以最大限度地减少其典型输入数据的冲突。 GetHashCode() 通常用于确定两个项目是否可能是同一个项目。需要进一步检查以确认这一点。
  • 溢出通常没有问题,您可以将代码包装在unchecked 部分中。无论如何,哈希并不是唯一的,因此两个不相等的数字可能具有相同的哈希码。但是,两个相等的数字必须具有相同的哈希码。
  • 通常结构体为equals和hashcodes提供了一个默认实现,这非常好。它是通过按位比较每个成员来实现的,因此无论如何您的实现似乎都是多余的。有关详细信息,请参阅stackoverflow.com/questions/8315656/…

标签: c# hashcode


【解决方案1】:

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

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

只要满足要求,造成溢出是可以的。

documentation 中也说明了这一点:

两个相等的对象返回相等的哈希码。然而,反之则不然:相等的哈希码并不意味着对象相等,因为不同(不相等)的对象可以有相同的哈希码。

您还可以在链接页面中查看GetHashCode 的其他实现。

【讨论】:

    猜你喜欢
    • 2013-03-19
    • 2015-09-22
    • 2014-05-02
    • 2010-11-15
    • 2016-08-21
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多