Objective-C:Fowler-Noll-Vo(FNV)哈希实现

时间:2010-05-18 10:53:50

标签: iphone objective-c hash fnv

我的iPhone项目中有一个HTTP连接器,查询必须使用Fowler-Noll-Vo(FNV)Hash从用户名中设置参数。

我目前正在使用Java实现,这是代码:

long fnv_prime = 0x811C9DC5;
long hash = 0;

for(int i = 0; i < str.length(); i++)
{
    hash *= fnv_prime;
    hash ^= str.charAt(i);
}

现在在iPhone方面,我这样做了:

int64_t fnv_prime = 0x811C9DC5;
int64_T hash = 0;

for (int i=0; i < [myString length]; i++)
{
    hash *= fnv_prime;
    hash ^= [myString characterAtIndex:i];
}

这个脚本没有给我与Java一样的结果。

在第一个循环中,我得到了这个:

hash = 0

hash = 100(首字母是“d”)

hash = 1865261300(对于hash = 100,fnv_prime = -2128831035,如Java)

有人看到我遗失的东西吗?

提前感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

在Java中,这一行:

long fnv_prime = 0x811C9DC5;

将在fnv_prime中产生数值-2128831035,因为该常量被解释为int,这是Java中的32位有符号值。然后,当用long

写入时,该值将被符号扩展

相反,在Objective-C代码中:

int64_t fnv_prime = 0x811C9DC5;

0x811C9DC5被解释为unsigned int常量(因为它不适合带符号的32位int),数值为2166136261.然后将该值写入{ {1}},并且没有任何扩展的迹象,因为就C编译器而言,值是正的。

因此,您最终会得到fnv_prime的不同值,这可以解释您的不同结果。

这可以通过添加“fnv_prime”后缀在Java中更正,如下所示:

L

强制Java编译器将常量解释为long fnv_prime = 0x811C9DC5L; ,其数值与Objective-C代码相同。

答案 1 :(得分:1)

符号扩展的区别在于将32位值0x811C9DC5分配给64位var。

答案 2 :(得分:1)

顺便提一下,0x811C9DC5 一个FNV素数(它甚至不是素数);它是32位FNV&#34;偏移基础&#34;。如果使用此值(以及更多哈希冲突),您将获得不正确的哈希值。 32位FNV素数的正确值是0x1000193。见http://www.isthe.com/chongo/tech/comp/fnv/index.html

答案 3 :(得分:0)

Java和Objective-c中的字符是否相同? NSString会给你unichars。