Ruc*_*cia 7 php delphi bit-manipulation
我在Delphi中有一个相当简单的函数,它接受一个字符串并根据该字符串产生一个散列整数:
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;
Run Code Online (Sandbox Code Playgroud)
我正在将它转换为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;
}
Run Code Online (Sandbox Code Playgroud)
如果你将字符串测试字符串传递给Delphi函数,你得到195831015但PHP返回72559895.我注意到差异只在7个字符后变得明显.如果测试字符串只是测试结果是相同的.
PHP似乎在将负整数向右移动时遇到一些困难,例如下面的行:
if ($X<>0){$Result = $Result ^ ($X>>24);}
Run Code Online (Sandbox Code Playgroud)
改为左移$ X << 24为变量X产生与Delphi相同的值,但结果仍然不同.
我错过了一些非常明显的东西吗?
编辑:这两个函数的输出是:
德尔福
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
因此,直到字符"i",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);
}
}
Run Code Online (Sandbox Code Playgroud)
这现在有效!还要感谢Ignacio的面具理念:)
你确定Delphi是对的而PHP是错的吗?
Delphi 的 shl 和 shr 显然对于有符号整数可能会出现不可预测的行为。请参阅:http://www.merlyn.demon.co.uk/del-bits.htm#SAR。Stockton 博士似乎暗示移位运算有两种类型:算术移位(保留符号)和逻辑移位。
文档(http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/expressions_xml.html)对于 shl/shr 对有符号整数的影响不是很清楚。然而,他们确实提到,对于无符号整数,shr/shl 乘以 1 只能与除法/乘以 2 相媲美。
我找不到 Stockton 博士(从第一个链接)所说的逻辑移位操作,但尝试更改 delphi 实现以使用无符号 8 字节类型(想到 DWORD )似乎合乎逻辑:-)看看有什么效果。