int hash的唯一int

时间:2013-05-06 12:31:43

标签: hash

我很好奇是否有一些简单和/或众所周知的哈希方法具有以下属性:

  1. 它将32位int转换为另一个32位int
  2. 没有两个不相等的输入产生相同的输出
  3. 从输出看两个输入相似(差异和位掩码)不应该立即显而易见,这意味着hash(a)和hash(a + 1)应该有非常不同的输出,应该hash(a)和hash(a& 0x100000)。 (这排除了简单地使用随机值进行异或。)
  4. 虽然理论上显然必须存在这样的系统,但实际上有没有呢?

5 个答案:

答案 0 :(得分:5)

实践中有很多!

一个简单的解决方案是将输入乘以任何奇数,并取结果的最后32位。那就是:

y = (x * YOUR_ODD_NUMBER) & 0xffffffff;
但是,这确实有一些缺点。它总是将零映射到零,如果你选择像3这样的小数字,那么映射将是相当明显的(类似地,如果你选择像0xffffffff这样的大数字你会得到另一个明显的映射),并且最低有效位不会改变。通常,低位会影响较高位,但高位不会影响较低位。

另一种方法是使用自身的移位版本的独占或数字:

x ^= x >> YOUR_FIRST_SHIFT;
x ^= x << YOUR_SECOND_SHIFT;
y = x ^ (x >> YOUR_THIRD_SHIFT);

您可以根据需要叠加尽可能多的这些微不足道的操作,试图隐藏各个阶段的弱点。即使一个操作本身不是很好,它也可以在更复杂的操作链中有用。例如,异或具有某些常数将避免仅通过乘法将零映射到零的问题,并且移位和异或技术允许低位受高位影响。

如果你看一下PRNGs,你会发现他们中的很多人有一个与他们的州几乎相同的时期。他们通过以你指定的方式置换状态来实现这一点 - 通过1:1映射,其中一个状态与下一个状态之间的关系不是太明显 - 然后它们呈现一些状态(或所有状态)作为伪随机数。一些PRNG和哈希也完成了一个回火阶段,他们执行这些映射中的另一个来隐藏他们自己的一些弱点。

如果你在循环中运行哈希函数,在每次迭代时将y反馈回x,那么你有一个PRNG,你可以用dieharder之类的工具测试它的随机性。

并非所有PRNG都具有理想长周期属性,并且该属性对于良好的散列函数不是必需的,但是一些PRNG算法可以是操作执行的有用思想来源,并且它们具有全面的分析。 / p>

答案 1 :(得分:3)

尝试反转数字的二进制表示形式:

17(10) = 1110(2) -> 10111(reversed, set first bit as indicator) = 23
18(10) = 10010(2) -> 101001 = 41

或将后半部分与下半部分互换:

17(10) = 11|10(2) -> 1011 = 11
18(10) = 100|10(2) -> 10100 = 20

我不确定,但似乎应该适合你。

答案 2 :(得分:2)

一个简单的解决方案是制作一个顺序改变数组。某些加密函数基于此方法。

uint8_t arr[32]={4,7,24,9,15,3,...}; // an order you know
uint32_t orgVal;
uint32_t modVal =0;
uint32_t pos = 1;

for (int i=0; i<32;i++) {
  modVal += (orgVal&pos)? (1>>arr[i]):0;
  pos*=2;
}

(代码是从头开始制作的,没有IDE或测试;它可能不起作用)

正如评论中所指出的,如果你看一下比特,差异将是最小的:0和1的数量将是相同的。要解决此问题,您可以考虑使用位顺序更改和xor 。然后原始值和结果值之间的差异将更加显着。

答案 3 :(得分:0)

这个很简单,但效率可能不高:

  • 随机置换所有32位整数。
  • 保存(相当大)的表格。

现在您可以通过两种方式应用它,只有那些有表的人才能知道该数字应该是什么。

答案 4 :(得分:0)

一种简单的方法:hash(x) = rotate-shl(x, K1) xor C

您可以结合多个简单操作来获得更多“随机”结果,例如rotate-shl/shrbit-reversexornot等等。