Mam dość prostą funkcję w Delphi, który pobiera ciąg i daje całkowitą hashed podstawie tego napisu:Delphi bitowe proc konwersji do 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;
jestem przekształcenie go do PHP, ale wyniki nie są to samo. To jest to, co mam w 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;
}
jeśli przejdą w teststring ciąg do funkcji Delphi dostać 195831015 jednak PHP zwraca 72559895. zauważyłem różnica staje się widoczna dopiero po 7 znaków. Jeśli ciąg testowy jest tylko testem, wyniki są identyczne.
PHP wydaje się mieć pewne trudności z przesunięcia ujemną liczbę całkowitą w prawo na przykład folowing wiersz:
if ($X<>0){$Result = $Result^($X>>24);}
zmieniony na przesunięcie w lewo $ X < < 24 daje te same wartości jak Delphi dla zmiennej X , ale wyniki są nadal różne.
Czy brakuje tu czegoś naprawdę oczywistego?
EDIT: Wyjście z dwoma funkcjami są:
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
więc nie aż znak "i", że PHP rozpoczyna wysiąść utwór z obliczeniami
EDIT2:
funkcja Dodany PHP zrobić logiczną prawy shift zamiast przesunięcia arytmetycznego:
function lshiftright($var,$amt)
{
$mask = 0x40000000;
if($var < 0)
{
$var &= 0x7FFFFFFF;
$mask = $mask >> ($amt-1);
return ($var >> $amt) | $mask;
}else{
return ($var >> $amt);
}
}
Działa to teraz! Również dzięki Ignacio za pomysł maski :)
Dzięki za podpowiedź - sprawdzenie instrukcji PHP ponownie ukazuje, że zmiana bitowa jest tylko arytmetyczna. Miałem to działające w Delphi z dodatkową maską bitową, ale potem pomyślałem, że lepiej byłoby zmusić PHP do zrobienia tego, co chcę - zobacz edycję dla dodatkowego kodu – Rucia