我在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中使用Integer
,long
和Long
,但我没有得到正确的结果。
如何在按位运算中“模仿”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”中移位),即
>>>
。使用该运算符给出 我是正确的结果。谢谢!
答案 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));
}
但这会做更多的计算而没有真正的优势。