5

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

我现在有一个 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 相同的结果。

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

哈希 = 0

hash = 100(第一个字母是“d”)

hash = 1865261300(对于 hash = 100 和 fnv_prime = -2128831035,就像在 Java 中一样)

有人看到我缺少的东西吗?

在此先感谢您的帮助 !

4

4 回答 4

4

在 Java 中,这一行:

long fnv_prime = 0x811C9DC5;

将产生fnv_prime数值 -2128831035,因为该常量被解释为int,它是 Java 中的 32 位有符号值。然后,该值在写入 a 时进行符号扩展long

相反,在 Objective-C 代码中:

int64_t fnv_prime = 0x811C9DC5;

the0x811C9DC5被解释为一个unsigned int常量(因为它不适合有符号的 32 位int),数值为 2166136261。然后将该值写入fnv_prime,并且没有符号可以扩展,因为就 C 编译器而言,值为正。

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

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

long fnv_prime = 0x811C9DC5L;

这会强制 Java 编译器将常量解释为 a long,其数值与使用 Objective-C 代码得到的数值相同。

于 2010-05-18T11:20:11.037 回答
2

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

于 2012-12-01T09:31:57.217 回答
1

将 32 位值 0x811C9DC5 分配给 64 位 var 的符号扩展有所不同。

于 2010-05-18T11:36:49.000 回答
0

Java和Objective-c中的字符是一样的吗?NSString 会给你 unichars。

于 2010-05-18T10:59:29.007 回答