2011-10-16 65 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位。 –