2010-05-18 11 views
5

Tengo un conector HTTP en mi proyecto de iPhone y las consultas deben tener un conjunto de parámetros desde el nombre de usuario usando el hash Fowler-Noll-Vo (FNV).Objective-C: Fowler-Noll-Vo (FNV) Implementación Hash

que tienen una implementación de Java que trabajan en este momento, este es el código:

long fnv_prime = 0x811C9DC5; 
long hash = 0; 

for(int i = 0; i < str.length(); i++) 
{ 
    hash *= fnv_prime; 
    hash ^= str.charAt(i); 
} 

Ahora en el lado iPhone, lo hice:

int64_t fnv_prime = 0x811C9DC5; 
int64_T hash = 0; 

for (int i=0; i < [myString length]; i++) 
{ 
    hash *= fnv_prime; 
    hash ^= [myString characterAtIndex:i]; 
} 

Este script no me da el mismo resultado tiene Java.

En primer bucle, me sale esto:

de hash = 0

de hash = 100 (primera letra es "d")

de hash = 1865261300 (por hachís = 100 y fnv_prime = - 2128831035 como en Java)

¿Alguien ve algo que me falta?

¡Gracias de antemano por la ayuda!

Respuesta

4

En Java, esta línea:

long fnv_prime = 0x811C9DC5; 

rendirá en fnv_prime el valor numérico -2128831035, debido a que la constante se interpreta como un int, que es un valor con signo de 32 bits en Java. Ese valor se extiende después de firmar cuando está escrito en un long.

Por el contrario, en el código de Objective-C:

int64_t fnv_prime = 0x811C9DC5; 

la 0x811C9DC5 se interpreta como una constante unsigned int (porque no encaja en un signo de 32 bits int), con valor numérico 2166136261. Este valor luego se escribe en fnv_prime, y no hay ninguna señal que extender ya que, en lo que respecta al compilador de C, el valor es positivo.

Por lo tanto, termina con valores distintos para fnv_prime, lo que explica sus distintos resultados.

Esto se puede corregir en Java mediante la adición de un "L" sufijo, como esto:

long fnv_prime = 0x811C9DC5L; 

que obliga al compilador de Java para interpretar la constante como un long, con el mismo valor numérico de lo que tienes con el código Objective-C

+0

En Java como en Obj-C obtengo el mismo valor para prime = -2128831035 En Java cuando pongo "0x811C9DC5L" obtengo el valor = 2166136261 – Dough

+0

No debe obtener -2128831035 en Obj-C. ¿Estás seguro de que esto no es un artefacto de cómo imprimir ese valor? (es decir, ¿usó "% lld" o "% d" en su 'printf()'?) –

+0

Y una pista que indica que -2128831035 no es el valor numérico correcto: ¡no es primo! -2128831035 = - (3 * 5 * 17 * 101 * 82657) –

0

¿Los caracteres en Java y Objective-c son los mismos? NSString te dará unichars.

+0

¡Gracias por su respuesta! Char, en Java en Objective-Cn devuelve el valor ASCII del char. Para exemple: a = 97 b = c = 99 d = 100 y así sucesivamente! – Dough

+0

@dough: definitivamente no usa ASCII, aunque los primeros 127 caracteres pueden tener los mismos valores numéricos. Como ejercicio, ¿qué obtienes si imprimes el carácter 'fl'? ¿Y cuál es el valor ASCII de 'fl'? –

+0

'fl' no es un personaje, son dos: ¡fyl! – Dough

1

Es una diferencia en la extensión de signo que asigna el valor de 32 bits 0x811C9DC5 a una var de 64 bits.

+0

Es, en realidad. –

1

Por cierto, 0x811C9DC5 es no un FNV principal (ni siquiera es primo); es la "base de desplazamiento" FNV de 32 bits. Obtendrá valores hash incorrectos si usa este valor (y más colisiones hash). El valor correcto para el primo FNV de 32 bits es 0x1000193.Ver http://www.isthe.com/chongo/tech/comp/fnv/index.html

Cuestiones relacionadas