这个哈希函数是唯一的吗?

时间:2016-08-04 15:20:13

标签: hash unique hash-function

假设散列整数从不溢出,以下生成的散列对于不同的键是否总是不同的? 密钥应该包含ascii编码字符。

我认为情况就是这样,因为我无法想到一个例外情况。

char[] arr = "abcd"
int hash = 0
for (int i=0; i<arr.size; i++) {
    hash += (i+1) * arr[i]
}

EDIT1:虽然以下是我原始问题的技术上正确的答案,但我应该提到密钥的域名是有效的电子邮件ID。因此,一些ascii字符不包括在内。不过,我会进行一些测试和报告。唯一的问题是枚举所有的烫发只能达到很小的长度。

无论如何,我的要求是根据email-id制作唯一ID,并将它们用作数据库中的主键。只是不想自己使用邮件ID。

EDIT2:显然,有很多碰撞。例如,03N @gmail.com的哈希==哈希的00P@gmail.com

...
040 == 012
041 == 013
042 == 014
043 == 015
044 == 016
045 == 017
046 == 018
047 == 019
048 == 01:
...

我需要一种不同的哈希算法。你能建议一下吗?

3 个答案:

答案 0 :(得分:4)

否:1 * 2 + 2 * 2 = 1 * 4 + 2 * 1例如。

char[] arr = {'\u0002','\u0002'}char[] arr = {'\u0004','\u0001'}

答案 1 :(得分:3)

这两个字符串将生成相同的哈希值:

"~ "
"@?"

以上内容完全由可打印的ASCII字符组成。

测试算法的蛮力方法是简单地尝试2个字符的所有组合,然后可能是3个或4个字符的所有组合,以了解唯一性。

char key[5] = {0};
bool used[65536] = {0};
for (key[0] = " "; key[0] < 128; key[0]++)
    for (key[1] = " "; key[1] < 128; key[1]++) {
        if (used[hashcode(key)]) {
            printf("failed %s", key);
        else
            used[hashcode(key) = true;
        }

答案 2 :(得分:0)

在编辑中回答关于寻求改进哈希函数的其他问题,您可以做的一个小改动是在添加总数之前将每个字符乘以素数。这不会保证不会发生冲突,但是应该减少它们,因为你添加的每个新术语都会间隔更多,并且是素数的倍数。我跳过前几个素数以获得更好的间距,因此可以将第一个字符乘以11,将第二个字符乘以13,将第三个乘以17,将第四个乘以19,依此类推。如果你的字符串不是太长,你就不需要一个非常大的素数表。

如果您真的想要获得幻想,可以考虑生成CRC,或者使用线性反馈移位寄存器技术来生成签名。在后者中,您可以将新字符(或新字符的选定位)与运行总计的最低8位进行异或,然后将整个总数旋转多个位。