2012-01-10 13 views
5

Busco a la equelent PHP para la funciónPHP hashCode interna Función

"SomeString".hashCode(); 

de JAVA. El hashCode que estoy buscando debe ser el mismo que se utiliza para indexar Hashmaps en PHP. Espero que usted me puede ayudar :)

EDIT:

bien conocer la función que estaba buscando su escrito en C y no está disponible en sí mismo pero gracias por su ayuda PHP!

ulong zend_inline_hash_func(char *arKey, uint nKeyLength) 
{ 
     ulong $h = 5381; 
     char *arEnd = arKey + nKeyLength; 

     while (arKey < arEnd) { 
       $h += ($h << 5); 
       $h += (ulong) *arKey++; 
     } 
     return $h; 
} 

Respuesta

6

Arkh y la solución github a la que hace referencia guiguoz van en la dirección correcta, pero ambas no tienen en cuenta que PHP convertirá el hash entero valor a un doble tan pronto como excede 2^61. La función java, que se calcula utilizando valores fijos de 32 bits de hardware fijo, implica un desbordamiento aritmético de 32 bits (intrínseco a la CPU) para mantener el valor como un entero de 32 bits con signo.

En PHP, tendrá que realizar manualmente que desbordamiento aritmético cada vez que el $ hash se actualiza:

function overflow32($v) 
{ 
    $v = $v % 4294967296; 
    if ($v > 2147483647) return $v - 4294967296; 
    elseif ($v < -2147483648) return $v + 4294967296; 
    else return $v; 
} 

function hashCode($s) 
{ 
    $h = 0; 
    $len = strlen($s); 
    for($i = 0; $i < $len; $i++) 
    { 
     $h = overflow32(31 * $h + ord($s[$i])); 
    } 

    return $h; 
} 

(edit: corregido% v error tipográfico)

+3

El método overflow32 es incorrecto (% v en lugar de $ v, y se divide por 0 en una máquina de 32 bits). En su lugar, la línea $ h = debería decir: '$ h = (int) (31 * $ h + ord ($ s [$ i])) & 0xffffffff;' – xryl669

+0

@ xryl669, su línea regresará mal en 'hashCode ("153193cc3139f12e") '. devuelve 3369976574 en lugar de -924990722. – ahoo

+0

Esto todavía no es aplicable para sistemas de 32 bits. – SOFe

3

No existe tal método disponible en php. Por lo tanto, deberá implementar el método correcto. Wikipedia da el algoritmo utilizado por Java.lang.hashCode que es utilizado por las cadenas que pienso, por lo que aquí es una versión de php rápida de la misma:

<?php 
function getStringHashCode($string){ 
    $hash = 0; 
    $stringLength = strlen($string); 
    for($i = 0; $i < $stringLength; $i++){ 
    $hash = 31 * $hash + $string[$i]; 
    } 
    return $hash; 
} 
+1

thx para este código, pero necesito EXACTAMENTE el mismo interno utilizado para construir hashmaps. – user982911

+1

Esta función es incorrecta, https://gist.github.com/andreyknupp/5061911 tiene una implementación correcta, pero aún produce hashes diferentes si la cadena tiene espacios en ella. – guigouz

1

spl_object_hash es probablemente el más cercano a lo que quiere, pero a pesar de la nombrarlo realmente no devuelve un hash del valor pasado, simplemente un identificador único interno. No sé si es el hash realmente utilizado debajo del capó para matrices, etc.

1

Aquí es mi 2 centavos para la implementación hashCode de java en PHP:

/** 
* Simulates java hashCode function 
* hash a string to 32 bit 
* @param str the string to hash 
* @return hashed 32 bit integer 
*/ 
function hashCode($str) { 
    $str = (string)$str; 
    $hash = 0; 
    $len = strlen($str); 
    if ($len == 0) 
     return $hash; 

    for ($i = 0; $i < $len; $i++) { 
     $h = $hash << 5; 
     $h -= $hash; 
     $h += ord($str[$i]); 
     $hash = $h; 
     $hash &= 0xFFFFFFFF; 
    } 
    return $hash; 
}; 
1

una versión UTF-8 con el apoyo emoji

function str_hashcode($s){ 
    $hash = 0; 
    $len = mb_strlen($s, 'UTF-8'); 
    if($len == 0) 
     return $hash; 
    for ($i = 0; $i < $len; $i++) { 
     $c = mb_substr($s, $i, 1, 'UTF-8'); 
     $cc = unpack('V', iconv('UTF-8', 'UCS-4LE', $c))[1]; 
     $hash = (($hash << 5) - $hash) + $cc; 
     $hash &= $hash; // 16bit > 32bit 
    } 
    return $hash; 
}