0

Java と C++ の 2 つの個別のアプリケーションがあります。両方に 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

私が見ることができる2つの問題があります。まず、C++ は を使用してuint32_tおり、3,297,211,900 という値を与えています。この数は、符号付き 32 ビット整数に収まるよりも大きく、Java は符号付き整数のみを使用します。ただし、-1,868,221,715 は 3,297,211,900 と等しくなく、signed int と unsigned int の違いを考慮してもです。

(Java 8 ではInteger.toUnsignedString(int)、符号付き 32 ビット int を符号なし文字列表現に変換する が追加されました。以前のバージョンの Java では、intを alongにキャストして、上位ビットをマスクすることができます: ((long) i) & 0xffffffffL。)

2 つ目の問題は、間違ったバージョンの を使用していることですgetBytes()。引数を取らないものは、デフォルトのプラットフォーム エンコーディングを使用して UnicodeStringを に変換しbyte[]ます。これは、システムの設定方法によって異なる場合があります。UTF-8、Latin1、Windows-1252、KOI8-R、Shift-JIS、EBCDIC などを提供している可能性があります。

String.getBytes()いかなる状況下でも、絶対に、絶対に、引数のないバージョンの を呼び出さないでください。非推奨、間引き、無人化、破棄、および削除する必要があります。

代わりs.getBytes("UTF-8")に (または取得することを期待している任意のエンコーディング) を使用してください。

Zen of Pythonが言うように、「明示的は暗黙的よりも優れています」。

この 2 つ以外に問題があるかどうかはわかりません。

于 2014-06-06T21:14:47.087 に答える
1
于 2014-11-26T02:20:16.533 に答える