2011-10-16 66 views
7

我在德爾福一個相當簡單的函數,它接受一個字符串,並基於該字符串的散列整數德爾福按位PROC轉換到PHP

function TfrmMain.HashElf(const Buf; BufSize : LongInt) : LongInt; 
var 
Bytes : TByteArray absolute Buf; 
I, X : LongInt; 
begin 
    Result := 0; 
    for I := 0 to BufSize - 1 do begin 
    Result := (Result shl 4) + Bytes[I]; 
    X := Result and $F0000000; 
    if (X <> 0) then Result := Result xor (X shr 24); 
    Result := Result and (not X); 
    end; 
end; 

我將其轉換爲PHP,但結果並不一樣。這是我在PHP中已經有了:

function HashElf($Buf, $BufSize){ 
    $Bytes = str_split($Buf); 

    for ($i= 0; $i<$BufSize;$i++){ 
    $Result = ($Result << 4) + Ord($Bytes[$i]); 

    $X = $Result & (0xF0000000); 
    if ($X<>0){$Result = $Result^($X>>24);} 

    $Result = ($Result & (~ $X)); 
    } 
    return $Result; 
} 

如果在字符串的TestString到Delphi函數傳遞你195831015但是PHP返回72559895.我注意到的差異後,才7個字符變得明顯。如果測試字符串只是測試結果是相同的。

PHP似乎有一些困難負整數右移例如如下因素行:

if ($X<>0){$Result = $Result^($X>>24);} 

改變爲左移$ X < < 24產生如Delphi的相同的值的變量X ,但結果仍然不同。

我在這裏錯過了一些非常明顯的東西嗎?

編輯: 的兩個函數的輸出是:

德爾福

Char: t Result: 116  X: 0 
    Char: e Result: 1957  X: 0 
    Char: s Result: 31427  X: 0 
    Char: t Result: 502948  X: 0 
    Char: s Result: 8047283 X: 0 
    Char: t Result: 128756644 X: 0 
    Char: r Result: 181058242 X: 1879048192 
    Char: i Result: 212577321 X: -1610612736 
    Char: n Result: 180011582 X: -1073741824 
    Char: g Result: 195831015 X: -1610612736 

PHP

Char: t $Result: 116   $X: 0 
    Char: e $Result: 1957  $X: 0 
    Char: s $Result: 31427  $X: 0 
    Char: t $Result: 502948  $X: 0 
    Char: s $Result: 8047283 $X: 0 
    Char: t $Result: 128756644 $X: 0 
    Char: r $Result: 181058242 $X: 1879048192 
    Char: i $Result: 212577417 $X: -1610612736 
    Char: n $Result: 180013310 $X: -1073741824 
    Char: g $Result: 195858503 $X: -1610612736 

所以它不是直到字符 「我」 在PHP開始跑題與計算

EDIT2:

加入PHP函數做邏輯右移,而不是算術移位的:

function lshiftright($var,$amt) 
{ 
    $mask = 0x40000000; 
    if($var < 0) 
    { 
    $var &= 0x7FFFFFFF; 
    $mask = $mask >> ($amt-1); 
    return ($var >> $amt) | $mask; 
    }else{ 
    return ($var >> $amt); 
    } 
} 

這就是現在的作品!也感謝伊格納西奧面具的想法:)

回答

1

你確定德爾福是正確的,PHP是錯誤的嗎?

德爾福的shl和shr顯然可以表現不可預知的簽署整數。參見:http://www.merlyn.demon.co.uk/del-bits.htm#SAR。斯托克頓博士似乎暗示有兩種類型的移位操作:算術移位(保持符號)和邏輯移位。

該文檔(http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/expressions_xml.html)不太清楚shl/shr對有符號整數的影響。然而,他們確實提到shr/shl乘以1只可與div /乘以2,對於無符號的整數。

我找不到Stockton博士(從第一個鏈接)調用邏輯移位操作,但它似乎是合乎邏輯的:-)嘗試更改delphi實現以使用無符號的8字節類型(DWORD來記住),看看有什麼影響。

+0

感謝您的提示 - 再次檢查PHP手冊,推測該位移僅爲算術。我在Delphi中使用了額外的位掩碼,但是後來我發現強制PHP執行我想要的操作會更好 - 請參閱編輯其他代碼 – Rucia

1

掩蓋你想要的位。

if ($X<>0){$Result = ($Result^($X>>24)) & 0xFF;} 
+0

謝謝,儘管我需要的位數是0x7FFFFFFF。這意味着Delphi和PHP之間的結果仍然不一致。另外,這兩個例程將相互結合運行,因此每次都需要產生相同的結果。 – Rucia

+0

如果你是右移24位然後否,你只剩下8位。 –