У меня есть довольно простая функция в 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;
Я конвертирую его в 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;
}
если передать строку тестовой строки в функцию Delphi, вы получите 195831015, однако PHP вернет 72559895. Я заметил, что разница становится очевидной только после 7 символов. Если тестовая строка является просто тестовой, результаты идентичны.
PHP, похоже, испытывает определенные трудности со смещением отрицательного целого числа вправо, например, следующей строки:
if ($X<>0){$Result = $Result ^ ($X>>24);}
изменено на сдвиг влево $ X << 24 выдает те же значения, что и Delphi для переменной X, но результаты все равно другие. </p>
Мне не хватает чего-то действительно очевидного здесь?
EDIT:
Вывод двух функций:
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
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
Так что до тех пор, пока персонаж "i" не начнет сбиваться с вычислений
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);
}
}
Теперь это работает! Также спасибо Игнасио за идею маски:)