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