我遇到了这个 C 代码,它是一种哈希算法,可以为相似的字符串生成相同的哈希值:
unsigned long kaz_hash(const char *str)
{
static unsigned long randbox[] = {
0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
};
long acc = 0;
while (*str) {
acc ^= randbox[(*str + acc) & 0xf];
acc = (acc << 1) | (acc >> 31);
acc &= 0xffffffffU;
acc ^= randbox[((*str++ >> 4) + acc) & 0xf];
acc = (acc << 2) | (acc >> 30);
acc &= 0xffffffffU;
}
return acc;
}
我正在尝试在 C# 中使用它,这是我想到的:
public static ulong kaz_hash(string str) {
ulong[] randbox = {
0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
};
long acc = 0;
foreach (long c in str) {
acc ^= (long)randbox[(c + acc) & 0xf];
acc = (acc << 1) | (acc >> 31);
acc &= 0xffffffffU;
acc ^= (long)randbox[((c >> 4) + acc) & 0xf];
acc = (acc << 2) | (acc >> 30);
acc &= 0xffffffffU;
}
return (ulong)acc;
}
但是,有一点不对劲。这 2 个函数不会产生相同的结果。
编辑
感谢所有评论和帮助。我终于能够完成这项工作。以下是工作版本:
public static uint kaz_hash(string str) {
uint[] randbox = {
0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
};
int acc = 0;
unchecked {
foreach (int c in str) {
acc ^= (int)randbox[(c + acc) & 0xf];
acc = (acc << 1) | (acc >> 31);
acc &= (int)0xffffffffU;
acc ^= (int)randbox[((c >> 4) + acc) & 0xf];
acc = (acc << 2) | (acc >> 30);
acc &= (int)0xffffffffU;
}
}
return (UInt32)acc;
}
最佳答案
我用“abc”、“abcd”和“abcde”尝试了下面的代码,C# 代码返回与 C++ 代码相同的值:
public static int kaz_hash(string str)
{
UInt32[] randbox = {
0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
};
int acc = 0;
foreach (UInt32 c in str)
{
acc ^= (int)randbox[(c + acc) & 0xf];
acc = (acc << 1) | (acc >> 31);
acc &= -1;
acc ^= (int)randbox[((c >> 4) + acc) & 0xf];
acc = (acc << 2) | (acc >> 30);
acc &= -1;
}
return acc;
}
关于这个 C 哈希函数的 C# 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30110822/