我的目标是使用 MD5 结果的结果来索引哈希表。我想对其执行模运算以在表中找到适当的插槽。我尝试将其转换为无符号长长类型。当我打印结果时,对于相同的 MD5 哈希,我每次都会得到一个不同的数字。MD5 哈希最初是一个无符号字符 *。有人可以告诉我我做错了什么吗?
这是我的功能:
int get_fp_slot(unsigned char * fingerprint, int size)
{
return (unsigned long long)fingerprint % size;
}
MD5 哈希是一个 128 位的数字。因此,为了获得最佳性能,您可能应该保留所有 128 位。
鉴于您的函数将 128 位哈希作为字符串,您需要将该字符串解析为一系列 4 个整数。您的字符串可能看起来像这样:
79054025255fb1a26e4bc422aef54eb4
那是一个 32 字节的十六进制字符串。如果是这样,您可以像这样提取二进制版本:
int v1, v2, v3, v4;
sscanf( &fingerprint[0], "%x", &v1 );
sscanf( &fingerprint[8], "%x", &v2 );
sscanf( &fingerprint[16], "%x", &v3 );
sscanf( &fingerprint[24], "%x", &v4 );
你现在做什么真的取决于你希望你的哈希有多好。如果您确实需要使用 32 位数字,那么只需将所有这些数字异或:
int hash = v1 ^ v2 ^ v3 ^v4;
您正在转换指针,即哈希的地址。当然,该地址与哈希值无关。
如何解决它取决于你想要什么。例如,您可以使用哈希的最后 16 个字节并将其解析为unsigned long long
,
// sanity and error checking omitted for brevity
int get_fp_slot(unsigned char *fingerprint, int size)
{
size_t len = strlen(fingerprint);
size_t offset = len < 16 ? 0 : len-16;
unsigned long long hash_tail = strtoull(fingerprint + offset,NULL,16);
return hash_tail % size;
}
或增量模数
// uses a helper hex_val that converts a hexadecimal digit to the integer it signifies
int get_fp_slot(unsigned char *fingerprint, int size)
{
unsigned long long hash_mod = 0;
while(*fingerprint) {
hash_mod = (16*hash_mod + hex_val(*fingerprint)) % size;
++fingerprint;
}
return hash_mod;
}
在您的代码中,您正在转换指针本身,而不是形成 MD5 值的字节!
一个 MD5 是 128 位,即 16 个字节。假设您的long long
类型是 64 位(8 字节),您可以将其表示为两个long long
值,然后对它们进行异或运算以获取哈希值。或者,如果您愿意,您可以简单地选择其中之一……哈希质量可能相似。
您没有说出来,但我假设您的指纹是指向具有 MD5 值的 16 字节数组的指针。然后:
unsigned long long a = *(unsigned long long*)fingerprint;
unsigned long long b = *(unsigned long long*)(fingerprint + 8);
return a ^ b;
请注意, 和 的值a
将b
取决于您机器的字节序。只要您不将散列发送到不同的架构,这并不重要。