从32位无符号整数迁移一个散列函数,从c ++ / Qt到java

时间:2016-01-31 12:30:20

标签: java c++ qt

我在C ++ / Qt中有这个功能:

quint32 updateHash(quint32 value, quint32 hash)
{
    return = hash ^ ((hash << 5) + (hash >> 2) + value);

}

我想用Java重写这个确切的行为。

首先尝试:

private int updateHash(int value, int hash)
{
    return hash ^ ((hash << 5) + (hash >> 2) + value);
}

该方法将连续多次调用。

只要生成的哈希低于2 ^ 16-1,Java版本就会给出相同的结果,所以我认为问题是C ++中的unsinged整数类型,以及Java中的带符号整数类型。

我尝试在Java中使用IntegerlongLong,但我没有得到正确的结果。

如何在按位运算中“模仿”Java中的unsigned int行为?

编辑:按要求,预期输出: 左:输入值,右:​​计算散列

First Hash为“0”,之后计算出的哈希值是下一个结果的输入哈希值。

使用C ++预期输出

87=>87
97=>2817
121=>92248
112=>2887134
111=>94417528
105=>2967391871
110=>4174335378
116=>2698169226
65=>3797741545
99=>1718212244
116=>2159844877
105=>3078518657
118=>2865822199
101=>771982389

使用Java输出

87=>87
97=>2817
121=>92248
112=>2887134
111=>94417528
105=>2967391871
110=>3100593554
116=>2966604682
65=>3059544041
99=>258594452
116=>4269579789
105=>827225985
118=>124582391
101=>3893789749

“110”输入变坏了。

Edit2:@dasblinkenlight的回答让我想到了正确的想法,我将复制我在这里发表的评论:

  

但是,在java中使用int并没有产生与使用相同的结果   C ++代码。

     

但是你的评论给了我正确的暗示   看。在C ++中,bitshift运算符<<>>在逻辑上工作   Java这些运算符的算术运算。所以右移会转移   如果整数为负,则为“1”,如果为整数则为零   正。

     

Java有一个特殊的右移运算符,它运作合理   (=总是在“0”中移位),即>>>。使用该运算符给出   我是正确的结果。谢谢!

1 个答案:

答案 0 :(得分:3)

如果不使用unsigned int,则无法在Java中模仿long:该语言中唯一的无符号类型为char,但它只有16位。

好消息是,就哈希码而言,数字签名/未签名绝对无关紧要。您的逐字翻译将生成与QT原始版本相同质量的哈希码,因此在哈希容器中使用它们将为您提供相同的结果。

您可以通过在方法中使用long来扩展Java和QT之间的结果与31位匹配的范围,即

// The caller will be passing int for value and hash
private int updateHash(long value, long hash) {
    return (int)(hash ^ ((hash << 5) + (hash >> 2) + value));
}

但这会做更多的计算而没有真正的优势。