0

我有 2 个独立的应用程序,一个是 Java,另一个是 C++。我同时使用 Murmurhash3。但是,在 C++ 中,对于相同的字符串,与 Java 相比,我得到了不同的结果

这是来自 C++ 的一个:https ://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp?r=144

我正在使用以下功能:

void MurmurHash3_x86_32 ( const void * key, int len,
                      uint32_t seed, void * out )

这是Java的一个:http ://search-hadoop.com/c/HBase:hbase-common/src/main/java/org/apache/hadoop/hbase/util/MurmurHash3.java||server+void+% 2522哈希

上面相同的 Java 代码有很多版本。

这就是我调用 Java 的方式:

String s = new String("b2622f5e1310a0aa14b7f957fe4246fa");
System.out.println(MurmurHash3.murmurhash3_x86_32(s.getBytes(), 0, s.length(), 2147368987));

我从 Java 得到的输出:-1868221715

我从 C++ 3297211900 得到的输出

当我测试其他一些示例字符串时,例如“7c6c5be91430a56187060e06fd64dcb8”和“7e7e5f2613d0a2a8c591f101fe8c7351”,它们在 Java 和 C++ 中匹配。

任何指针表示赞赏

4

2 回答 2

2

我可以看到两个问题。首先,C++ 使用uint32_t, 并给出 3,297,211,900 的值。这个数字比有符号的 32 位 int 大,Java 只使用有符号整数。但是,-1,868,221,715 不等于 3,297,211,900,即使考虑了有符号整数和无符号整数之间的差异。

(在 Java 8 中,他们添加了Integer.toUnsignedString(int),它将有符号的 32 位 int 转换为其无符号字符串表示。在早期版本的 Java 中,您可以将int转换为 along然后屏蔽高位:((long) i) & 0xffffffffL。)

第二个问题是您使用了错误的getBytes(). 不带参数的那个使用默认平台编码将 Unicode 转换String为 a byte[],这可能会因您的系统设置方式而异。它可能会为您提供 UTF-8、Latin1、Windows-1252、KOI8-R、Shift-JIS、EBCDIC 等。

String.getBytes()在任何情况下,永远不要调用 的无参数版本。它应该被弃用、淘汰、去窗、销毁和删除。

改用s.getBytes("UTF-8")(或您期望获得的任何编码)。

正如Python 之禅所说,“显式胜于隐式”。

我不知道除了这两个之外是否还有其他问题。

于 2014-06-06T21:14:47.087 回答
1
于 2014-11-26T02:20:16.533 回答