que tienen una función bastante simple en Delphi, que toma una cadena y produce un número entero hash basado en esa cadena:Delphi bit a bit proc convertido a 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;
estoy convertirlo en PHP, pero los resultados no son lo mismo. Esto es lo que tengo en 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;
}
si pasa en el TestString cadena a la función de Delphi que presentamos lo mejor 195831015 embargo PHP devuelve 72559895. Me di cuenta de la diferencia sólo se hace evidente después de 7 caracteres. Si la cadena de prueba es solo prueba, los resultados son idénticos.
PHP parece tener cierta dificultad con el cambio de un entero negativo a la derecha, por ejemplo, la línea de folowing:
if ($X<>0){$Result = $Result^($X>>24);}
cambió a desplazamiento a la izquierda $ X < < 24 produce los mismos valores que Delphi para la variable X , pero los resultados aún son diferentes.
¿Me falta algo muy obvio aquí?
EDIT: La salida de las dos funciones son:
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
Así que no es hasta el carácter "i" que PHP comienza a salirse de pista con los cálculos
EDIT2:
Añadida función PHP para hacer un desplazamiento lógico a la derecha en lugar de desplazamiento aritmético:
function lshiftright($var,$amt)
{
$mask = 0x40000000;
if($var < 0)
{
$var &= 0x7FFFFFFF;
$mask = $mask >> ($amt-1);
return ($var >> $amt) | $mask;
}else{
return ($var >> $amt);
}
}
Esto funciona ahora! También gracias a Ignacio por la idea de máscara :)
Gracias por la sugerencia: revisar el manual de PHP de nuevo revela que el cambio de bit es solamente aritmético. Lo tuve trabajando en Delphi con una máscara de bits adicional, pero luego pensé que sería mejor forzar a PHP a hacer lo que quisiera - ver edición para código adicional – Rucia