【问题标题】:C# GetHashCode with two Int16, also returns only up to Int32?C# GetHashCode 有两个 Int16,也只返回 Int32?
【发布时间】:2012-04-14 18:11:22
【问题描述】:

很抱歉把两个问题合二为一,它们是相关的。

HashCodes 用于HashSets 等。据我了解,它们必须是唯一的,不能更改,并且将对象的任何配置表示为单个数字。

我的第一个问题是,对于我的对象,包含两个 Int16s ab,我的 GetHashCode 返回类似 a * n + b 的东西是否安全,其中 n 是一个很大的数字,我想也许是 @ 987654327@?

另外,GetHashCode 似乎不灵活地专门返回 Int32 类型。

32bits可以存储,例如两个Int16s,一个unicode字符或者16个N、S、E、W罗盘方向,不多,甚至像一个小的几个节点图可能太多了.这是否代表 C# Hash 集合的限制?

【问题讨论】:

  • 我会使用 (a << 16) | b,它恰好是独一无二的,并且没有复杂的数学运算
  • 这不是唯一的,您忘记了符号扩展。 (a

标签: c# hash int gethashcode int32


【解决方案1】:

据我了解,它们必须是独一无二的

不。对于大多数类型来说,它们不可能是唯一的,它们可以有超过 232 个可能的值。理想情况下,如果两个对象具有相同的哈希码,那么它们不太可能 是相等的——但你永远不应该假设它们 相等的。重要的一点是,如果它们有不同的哈希码,它们肯定应该不相等

我的第一个问题是,对于包含两个 Int16 a 和 b 的对象,我的 GetHashCode 返回类似 a * n + b 之类的东西是否安全,其中 n 是一个大数,我想也许 Math.Pow(2 , 16).

如果它包含两个Int16值,那么使用起来最简单:

return (a << 16) | (ushort) b;

那么值是唯一的。万岁!

还有GetHashCode 似乎不灵活地专门返回类型Int32

是的。 DictionaryHashSet 等类型需要能够使用固定大小,以便它们可以使用它来将值放入存储桶中。

32bits可以存储,例如两个Int16s,一个unicode字符或者16个N、S、E、W罗盘方向,不多,甚至像一个小的几个节点图可能太多了.这是否代表 C# Hash 集合的限制?

如果它限制,那将是 .NET 限制而不是 C# 限制 - 但不,这只是对哈希码的含义的误解。

Eric Lippert 有一个出色的(显然)blog post about GetHashCode,您应该阅读它以了解更多信息。

【讨论】:

  • 感谢您的明确答复。他们不必是独一无二的吗?所以它可以“返回 0;”如果效率低下,它仍然可以工作吗?
  • @alan2here:是的。返回常量始终是哈希码的有效策略 - 但它会破坏与哈希表等相关的所有正常效率。
  • ",如果两个对象具有相同的哈希码,那么它们un可能是相等的 - 但你永远不应该假设它们是 unequal" 你把这句话搞砸了
  • 所以哈希码是一种相似度的数值估计。此外,我在“return (a
  • 乔恩,正如 Hans Passant 在 cmets 中提醒 Marc Gravell 关于这个问题的那样,@alan2here 不应该忽略该警告。如果他这样做了,对于任何负的b 值,所有a, b 对都将具有相同的哈希码,而不管a 的值如何。如果 b 小于零,((a &lt;&lt; 16) | b) == b,因为符号扩展。
【解决方案2】:

GetHashCode 对于对象的每个实例来说不是(也不能是)唯一的。以Int64为例;即使散列函数是完美分布的,也会有 2 40 亿 Int64s 散列到每个值,因为正如你提到的,散列码只是一个Int32

但这并不是对使用哈希码的集合的限制;它们只是将存储桶用于哈希到相同值的元素。因此,不能保证对哈希表的查找是单个操作。获取正确的存储桶是一个操作,但该存储桶中可能有多个项目。

【讨论】:

  • 如果散列函数分布良好,那么每个 32 位散列当然会有 40 亿 个冲突。
  • 不是 2 个Int64s 每个 Int32 哈希值,而是 4294967296。2^64 / 2^32 等于 2^32。
  • @EricLippert, phoog:你当然是对的。我脑子里的东西看到 32 和 64 并自动转到 64/32 而不是 2^64/2^32...
猜你喜欢
  • 2012-06-02
  • 1970-01-01
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 2011-04-23
  • 2014-02-22
相关资源
最近更新 更多