2016-01-31 63 views
1

我在C++/Qt的有這樣的功能:migrationg與C++/Qt的32位無符號整數哈希函數的Java

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,longLong,但我沒有得到正確的結果。

如何在按位操作中「模仿」Java中的unsigned int行爲?

編輯:按照要求,期望的輸出: 左:輸入值,右:​​計算的散列

第一哈希爲「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++中,位移運算符<<>>工作邏輯,在 Java這些運算符工作算術。因此,如果整數爲負,則右移將在 中移動「1」,如果整數爲 爲正,則移位爲0。

Java有一個特殊的右移運算符,其邏輯運算邏輯爲 (=總是移入「0」),即>>>。使用該運算符給出 我是正確的結果。謝謝!

+1

請給出一個輸入,一個期望的輸出和實際的輸出(最好是十六進制)。 –

+0

我將輸出添加到原始帖子。 – Marc

回答

3

不能模仿的Java unsigned int不使用long:在語言中唯一的無符號的類型是char,但它只有16位。

好消息是,就散列碼而言,絕對沒關係數字是有符號的/無符號的。您的逐字翻譯將產生與QT原件相同質量的哈希碼,因此在哈希容器中使用它們會給您相同的結果。

你可以擴展在Java和QT的結果將通過long方法內匹配到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)); 
} 

但這會做更多的計算,沒有真正的優勢。

+0

但是,在java中使用int並不會產生與使用C##代碼相同的結果。 但是你的評論給我提供了我必須看的正確提示。 在C++中,位移運算符「<<" and ">>」工作邏輯,在Java中這些運算符工作在算術運算。所以如果整數爲負,則右移將以「1」移位,如果整數爲正,則右移將爲零。 Java有一個特殊的右移運算符,它符合邏輯(=總是移入「0」),即「>>>」。使用該運算符可以給我正確的結果。 謝謝! (對不起,我無法格式化此評論...) – Marc