6

我需要在 Python 和 Scala 中使用 MurmurHash 字符串。然而,他们给出了非常不同的结果。Scala 的内置MurmurHash3库似乎没有提供与我尝试过的任何其他库(包括在线库)相同的结果。奇怪的是它似乎匹配单个字符而不是多个字符。这里有些例子:

Python:

mmh3.hash('string', 0)
res: -1390314837

斯卡拉:

MurmurHash3.stringHash("string", 0)
res: 379569354

我已经尝试过使用有符号和无符号整数,因为我知道 Java 已经签名并且 python 正在包装的 C 实现正在使用无符号。但即使使用 NumPy 转换为带符号的 int 也无济于事。这个网站似乎同意python实现:

http://murmurhash.shorelabs.com/

关于这里可能发生什么的任何想法?

4

2 回答 2

3

Scala 使用编码为 UTF-16 的 Java 字符串。它们一次打包两个成一个Int; Python 使用 a char*(8 位),因此一次包含四个字符而不是两个。

编辑:Scala 还按 MSB 顺序打包字符,即(s.charAt(i) << 16) | (s.charAt(i+1)). 如果获得完全相同的答案真的很重要,您可能需要切换到一系列短裤,然后交换每一对短裤。(或者将 Scala 代码移植到 Python,反之亦然。)它还以字符串长度结束;我不确定 Python 是如何合并长度数据的,如果有的话。(这很重要,因此您可以区分字符串"\u0000""\u0000\u0000"。)

于 2016-08-27T05:59:49.873 回答
3

这是由于 ScalaMurmurHash3.stringHashMurmurHash3.bytesHash

MurmurHash3.bytesHash和 pythonmmh3.hash将字符以 4 个为一组传递给散列混合器,但MurmurHash3.stringHash以 2 个为一组混合字符。这意味着两个散列函数返回完全不同的输出:

import scala.util.hashing.MurmurHash3

val testString = "FiddlyString"

MurmurHash3.stringHash(testString)           /* Returns an int */
MurmurHash3.bytesHash(testString.getBytes()) /* Returns a different int */

因此,如果您需要 python 和 Scala 的MurmurHash3值的结果完全匹配:

我建议第一个选项,特别是如果您的用例需要更好的性能,或者您需要散列大量字符串

于 2017-09-28T15:28:26.967 回答