Hola colegas estadísticos,
Tengo una fuente que genera hashes (por ejemplo, computando una cadena con una marca de tiempo y otra información y hasheándola con md5) y quiero proyectarla en un número fijo de cubetas (digamos 100).
hash de ejemplo: 0fb916f0b174c66fd35ef078d861a367
Lo que pensé al principio fue usar solo el primer carácter del hash para elegir una cubeta, pero esto conduce a una proyección muy no uniforme (es decir, algunas letras aparecen muy raramente y otras muy frecuentemente)
Luego, intenté convertir esta cadena hexadecimal en un entero usando la suma de los valores de los caracteres, luego tomar el módulo para elegir una cubeta:
import sys
for line in sys.stdin:
i = 0
for c in line:
i += ord(c)
print i%100
Parece funcionar en la práctica, pero ¿no sé si hay algún sentido común o resultados teóricos que puedan explicar por qué y en qué medida esto es cierto?
[Editar] Después de pensarlo un poco llegué a la siguiente conclusión: En teoría, puedes convertir el hash en un entero (muy grande) interpretándolo como un número: i = h[0] + 16*h[1]+16*16*h[2] ... + 16^31*h[31] (cada letra representa un número hexadecimal). Luego podrías tomar el módulo de este número grande para proyectarlo al espacio de las cubetas. [/Editar]
¡Gracias!
3 votos
Un hash real no debería dar resultados tan no uniformes. ¿Estás seguro de que el algoritmo de hash está correctamente implementado?
0 votos
Dudo que haya un error en el algoritmo de hash en sí mismo. Pero sospecho que los caracteres del resumen en hexadecimal no son estrictamente uniformes y distribuidos de manera independiente.
1 votos
Eso es lo que encuentro dudoso: un hash "criptográficamente seguro" como MD5 debería tener distribuciones uniformes de todos los dígitos, a menos que haya algo muy especial acerca de la distribución de la entrada ("especial" significa estar íntimamente relacionado con el algoritmo MD5). Tu solución propuesta equivale a volver a hacer hash al hash, lo cual no debería ser necesario en absoluto.
1 votos
El primer carácter del hash Md5 debe ser uniforme. Pero solo obtendrías 16 valores (es una codificación hexadecimal)
1 votos
Gracias por insistir en ese punto, volví a ejecutar mi conteo en la primera letra de los hashes y parece estar efectivamente ~uniformemente distribuido : {'a': 789, 'c': 769, 'b': 755, 'e': 730, 'd': 804, 'f': 749, '1': 716, '0': 758, '3': 734, '2': 735, '5': 787, '4': 756, '7': 771, '6': 721, '9': 764, '8': 765}. Por lo tanto, mi pregunta está más o menos respondida ya que solo necesito proyectar este generador aleatorio de 16 estados a un espacio de 100 estados, lo cual se puede hacer utilizando las primeras 2 letras del hash para generar un entero en el rango [0,16+16*16] y luego hacer el módulo de 100. ¿Te importa si respondo mi propia pregunta?
0 votos
@oDDsKooL Deberías copiar este comentario en una respuesta, luego seleccionarlo como la respuesta correcta. De esa manera, esta pregunta quedará marcada como respondida.
0 votos
Sí, puedes responder tu propia pregunta: ver meta.stackexchange.com/questions/17463/…