【问题标题】:Creating Hash Code and Overflow创建哈希码和溢出
【发布时间】:2014-07-01 01:04:57
【问题描述】:

我正在尝试从两个整数输入生成哈希码。

中概述的方法

Combining Java hashcodes into a "master" hashcode

似乎适用于许多输入值。但是,当输入整数之一是 int.MinValue 时,行为似乎不太理想。具体我观察

int.MinValue * 1013 == int.MinValue

int.MinValue * 1009 == int.MinValue

但是

int.MinValue * 2 == 0

int.MinValue * 20 == 0

所有这一切都在一个未经检查的上下文中。

我会天真地(并且错误地)假设int.MinValue * (something other than 1 or 0) 会产生不同于int.MinValue0 的新位模式。

问题

  1. 为什么将int.MinValue 乘以这些常数会产生int.MinValue(2 个案例)或0(2 个案例)?
  2. int.MinValue 的行为是否表明哈希算法存在缺陷?

【问题讨论】:

  • 可能表明那个散列算法存在缺陷,但并非所有散列算法都仅通过乘法来实现。事实上,看看 .NET 通常是如何做的,将一个素数相加并与另一个素数相乘。添加可能表明此“缺陷”的修复。
  • @LasseV.Karlsen:与其他替代方案相比,这种创建哈希的方法似乎被认为是有缺陷的。旋转哈希似乎是更合适的选择eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx

标签: c# hashcode


【解决方案1】:

乘法或多或少是向左移动位。因为int.MinValue0x80000000(只设置了一个最高位),所以乘法只能产生两个 int 值 - 0(如果乘以偶数)或仍然设置最高位的值(对于奇数)。

4 位数字的示例(x,y,z - 特定位的任何值,1000 等效于 int.MinValue

1000 * xyz1 =
   (xyz0 * 1000)  + 1000 * 1 = 
   (xyz  * 10000) + 1000 * 1 =  
   (xyz  * 0)     + 1000 = 1000

1000 * xyz0 = 
   (xyz  * 10000) + 1000 * 0 =  0

【讨论】:

  • 所以这意味着对于素数 P 如果 P * inputValue 2 一定是奇数?这似乎表明 int.MinValue 附近的值存在大量哈希冲突。在返回哈希值之前在long 中执行数学运算然后再转换回int 会更好吗?
  • 我不擅长概率和散列专家,所以我不能说问题有多严重。对我来说,这感觉不是很常见 - 你要么散列一次(并且应该得到随机分布)或组合多个散列值 - 让所有散列接近 int.MinValue 感觉不太可能。我添加了“hashcode”标签,因此有更多有用的相关问题 - 查看stackoverflow.com/questions/34595/…,因为它似乎有关于散列的合理讨论/链接。
  • 我认为就我的目的而言,边缘情况并不重要。出于一般目的,我了解到这种组合哈希的方法不是很好,并且会使用更像旋转哈希eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 2013-03-05
  • 1970-01-01
  • 2011-09-20
  • 2017-01-31
  • 2021-02-21
相关资源
最近更新 更多