繁体   English   中英

四个无符号整数的散列函数(C ++)

[英]Hashing function for four unsigned integers (C++)

我正在编写一个程序,它产生四个无符号32位整数作为某个函数的输出。 我想要散列这四个整数,所以我可以将这个函数的输出与未来的输出进行比较。

我在编写一个像样的散列函数时遇到了麻烦。 当我最初编写这段代码时,我简单地添加了四个整数中的每一个,我知道这是不够的。 我尝试了其他几种技术,例如转移和添加,但无济于事。 我得到一个哈希,但质量很差,而且这个功能产生了大量的碰撞。

散列输出可以是32位或64位整数。 所讨论的函数会产生数十亿个哈希值,因此冲突在这里是一个真正的问题,我愿意使用更大的变量来确保尽可能少的冲突。

任何人都可以帮我弄清楚如何编写一个高质量的哈希函数?

为什么不将四个整数存储在合适的数据结构中并进行比较呢? 除非存储是个问题,否则在这种情况下散列它们的好处对我来说是可疑的。

如果存储是问题,您可以使用此处分析的散列函数之一。

这是一个相当合理的哈希函数,从4个整数到1个整数:

unsigned int hash = in[0];
hash *= 37;
hash += in[1];
hash *= 37;
hash += in[2];
hash *= 37;
hash += in[3];

通过均匀分布的输入,它可以提供均匀分布的输出。 输入的所有位都参与输出,每个输入值(尽管不是每个输入位)都会影响每个输出位。 有可能它比产生输出的功能更快,在这种情况下没有性能问题。

还有其他具有其他特征的哈希值,但是除非另有证明,否则累积乘以素数是一个良好的开端。 如果您愿意,可以尝试使用xor而不是添加来累积。 无论哪种方式,都很容易产生碰撞(例如{1,0,a,b}与{0,37,a,b}碰撞所有a,b),所以你可能想要选择一个你认为具有的素数与您的函数中任何合理的实现错误无关。 因此,如果你的函数中有很多modulo-37算术,那么可以用1000003代替。

因为散列可能会产生冲突,所以无论如何都必须将密钥保存在内存中才能发现这些冲突。 哈希映射和其他标准数据结构在内部簿记中执行此操作。

由于密钥太小,只需直接使用密钥而不是散列。 这将更快,并将确保没有碰撞。

我完全同意Vinko - 只是比较它们。 如果您仍然需要良好的散列函数,则需要分析4个非整数整数的分布。 然后,您必须以某种方式制作散列函数,结果将均匀分布在32位散列值的整个范围内。

一个简单的例子 - 让我们假设大多数时候,每个函数的结果都在0到255之间。然后你可以很容易地将每个函数的低8位混合到你的哈希中。 大多数情况下,你直接得到结果,有时候(当一个函数返回一个更大的结果时)你就会发生碰撞。

总结一下 - 如果没有信息如何分配4个函数的结果,我们无法帮助您获得良好的散列函数。

为什么哈希? 看起来像std :: set或std :: multi集合更适合存储这种输出。 您需要做的就是将四个整数包装在一个结构中并编写一个简单的比较函数。

尝试使用CRCFNV FNV很好,因为它很快并且具有折叠位的定义方法以获得“较小”的散列值(即12位/ 24位/等)。

此外,从128位(4 X 32位)数字生成64位哈希的好处有点值得怀疑,因为正如其他人所建议的那样,您可以将原始值用作集合中的键。 您确实希望散列中的位数表示您最初拥有的值的数量。 例如,如果数据集具有100,000个4X32位值,则可能需要17位或18位散列值,而不是64位散列值。

可能有点矫枉过正,但考虑一下Boost.Hash 生成非常简单的代码和良好的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM