我的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)
有人看到我遗失的东西吗?
提前感谢您的帮助!
答案 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。