13 votos

Curiosas propiedades de 33

Debido a que mi explicación haya tantas palabras, voy a empezar con mi pregunta y, a continuación, se puede leer la explicación en caso de que usted necesita:

El Bernstein Hash método utiliza el número 33 como un multiplicador. Por lo que he leído Bernstein mismo no tiene explicación razonable de por qué 33 tiene propiedades útiles. Me pregunto si las matemáticas de la comunidad tiene alguna de las teorías sobre la materia.


La explicación:

Soy un ingeniero de software y recientemente estuve trabajando en una entrada de blog acerca de una función de hash que yo estaba escribiendo. En el proceso de diseño de mi función hash, miré a una gran cantidad de implementaciones de otras funciones de hash.

Para los no programadores, lo esencial es que el hashcodes producida por los objetos deben estar bien distribuidos en todo el rango de valores de 32 bits con signo (- 2.147.483.648 a 2.147.483.647).

Digamos que tengo la cadena "ABCD." Una función hash sería el bucle a través de cada personaje, obtener el valor ASCII de la misma, de hacer algo, y colocarlo en un compuesto hashcode.

Por ejemplo, en una gran cantidad de implementaciones, que iban a tomar un hashcode se inicializa con un gran primer, multiplíquelo por otro primer y el XOR con el valor de 'a', que es de 65 años. Entonces, había que tomar y se multiplica por el mismo primer y XOR que con el valor de 'B'. Que iba a hacer esto hasta el final de la cadena es alcanzado.

He encontrado una aplicación inteligente en el marco de Java de código que se repite a lo largo de cada elemento y efectivamente se aplica esta: $i = ((i \ll 5) - i) \oplus j$. Yo estaba confundida al principio, hasta que me funcionó de esa $(i \ll 5) - i = 31i$. Para un equipo que, poco cambio es más rápido que el multiplicando así que esta es una forma inteligente de multiplicar por un número primo.

Así, miré en el de Microsoft .Net framework y me encontré con que lo hacen de una manera un poco diferente. Que el uso de $(i \ll 5) + i$ lugar! Yo no podía entender por la vida de mí ¿por qué se utiliza 33 en lugar de 31 porque por lo que entiendo que la multiplicación por números primos es la base de muchos de hashing y de cifrado funciones.

Me enteré de que esta técnica se llama la de Bernstein Hash y que Bernstein mismo no sé por qué 33 producen una buena distribución de los valores como un multiplicador de las funciones de hash.

3voto

palehorse Puntos 8268

Siempre he asumido que el factor de 33 (lo que equivale a un 5-desplazamiento de bits, además de una suma, como se nota) fue elegido por 5 bits es más o menos el contenido significativo de (ASCII) de texto, de ahí la "difusión" es el lugar óptimo para la típica textual claves. Dudo que algo más se puede decir de los estrictamente punto de vista matemático.

"por lo que entiendo que la multiplicación por números primos es la base de muchos de hashing y de cifrado funciones." Eso suena bastante vago para mí: por ejemplo, para el lineal congruential generadores, el multiplicador es con frecuencia no prime. Empíricamente, se observa que el 31 o 33 hacer muy poca diferencia. Tenga en cuenta que las funciones de hash generalmente relajar los requisitos estrictos de funciones de cifrado, en favor de la simplicidad y rendimiento.

Algunos razonable de la heurística y los resultados experimentales se dan aquí.

Ver también esta vieja discusión acerca de los 33 vs 31 de cosa.

3voto

lowglider Puntos 562

Yo no estoy muy familiarizado con este particular, la función de hash, pero me decidí a tratar de ir en busca de la fuente, que en este caso parece ser el grupo de noticias de Usenet comp.lang.c. En este mensaje, Phong Vo[drew] señala que una ventaja de más de 33 31 es que es congruente con 1 modulo 4, por lo que el $k \mapsto 33*k + c \pmod{2^n}$, para un determinado $c \ne 0$, es una permutación cíclica en $\mathbb Z / 2^n \mathbb Z$. En particular, esto significa que, si usted alimenta a la función de hash constante (no-cero) de entrada, se comporta como un período completo LCRNG.

Por supuesto, esto en realidad no prueban nada; es solo sugerente. También tenga en cuenta que esta explicación no se aplican directamente a la versión XOR en lugar de la adición a la mezcla en los datos. (Ambas parecen haber sido recomendado por Bernstein en varias ocasiones). En la práctica, por supuesto, yo no esperaría mucho de la diferencia entre el XOR y además de las variantes de todos modos; son muy similares operaciones, y debe mezclar en la entrada tan bien.

Como leonbloy, también sospecho que parte de la razón por la que 33 (o 31) funciona tan bien en la práctica puede ser que la típica entrada a tales funciones, es a menudo de texto ASCII, que tiende a tener la mayoría de su entropía en el menor de cinco bits. Por lo tanto, cambiando el valor de hash de la izquierda por cinco bits por ronda debería difundir esta entropía de manera muy eficiente a través de todos sus bits.

También, vale la pena señalar que esta función nunca fue pensado para ser un buen hash; fue diseñado para ser rápido, sin embargo, todavía aceptablemente buena, hash para aplicaciones donde la velocidad de la mezcla de cadenas es un factor limitante.

3voto

JiminyCricket Puntos 143

Ilmari y leonbloy ya han dicho bastante y proporciona conexiones pertinentes; he aquí algunas ideas:

En primer lugar, acerca de los números primos: el aceptado la respuesta a esta pregunta en stackoverflow suena bien para mí. No es que el multiplicador o el tamaño de la tabla hash deben ser primos; que debe ser sólo coprime. Si usted está escribiendo el código, por tanto, no hay razón para que ellos se prime, pero si usted está escribiendo el código para que sólo uno de ellos (lo cual sucede a menudo en la práctica), es posible que desee elegir los números primos, o al menos con los números primos grandes factores, para reducir las posibilidades de un "primer choque" entre el multiplicador y el tamaño de la tabla hash.

Segundo, acerca de hashcodes ser "bien distribuida" o "de forma óptima propagación": Eso es sólo parte de la historia. Para cadenas largas, donde la inyectividad no es una opción, la dispersión aleatoria es buena, pero para cadenas cortas, de inyectividad es incluso mejor que la dispersión aleatoria. Idealmente, un multiplicador basado en la función hash debe tener una extensión aleatoria inicial de entradas, pero ser inyectiva con respecto a las últimas entradas.

Los códigos ASCII de las letras de la misma caso de que sólo se diferencian en el bajo $5$ bits. Así que para las cadenas que terminan en letras minúsculas y $32$-bit valores de hash, usted puede obtener de inyectividad con respecto a los últimos seis caracteres, si el multiplicador es mayor que $32$, mientras que para los multiplicadores de menos de $32$ el bit más bajo de la penúltima entrada de influencias en la mayoría de los últimos $5$ bits y por lo tanto su contribución no es linealmente independientes de las contribuciones de todos los demás bits. En el caso de que usted está usando sólo la mitad de la disposición de los valores hash, y los valores de los últimos seis entradas formar parejas que se asignan a los mismos valores de hash.

Si el multiplicador es mayor que $32$, y la multiplicación no se desborde, de inyectividad con respecto al último de los $6$ caracteres en minúsculas está garantizada. Este es el caso, hasta un multiplicador de $47$ (desde $2^4\cdot47^5\lesssim2^{32}$), pero más allá de eso, las contribuciones de los distintos bits generalmente son linealmente independientes (hay una buena oportunidad para $30$ random vectores en $\mathbb F_2^{32}$ a es linealmente independiente); el primer impar multiplicador para los que no están es $95$.

Así que no es inmediatamente claro por qué se $33$ debe ser mejor para cadenas de caracteres ASCII que cualquier otro impar multiplicador mayor que $32$ resto $1$ mod $4$ (ver Ilmari la respuesta). Sin embargo, en términos más generales, menor es el multiplicador, el final más entradas se correlacionan injectively antes de que empiecen revueltos por el desbordamiento. Por lo que bien podría ser que el $33$ es un buen trade-off entre la obtención de la parte inferior $5$ bits de los caracteres ASCII de cada uno de los otros de la manera que requiere el $f\ge32$) y el retraso de la aparición de la codificación, por desbordamiento (que requiere un bajo $f$).

Una nota sobre la diferencia entre el XOR variante y la donde $j$ lugar: Mi consideraciones anteriores sobre la independencia lineal sólo se aplican a la operación XOR caso, en el que nos puede tratar el valor de hash como un vector en un $\mathbb F_2^{32}$ y la función de hash como una transformación afín en ese espacio. En el caso de la suma, no es necesario que el multiplicador sea mayor que la de $32$ para el hash a ser inyectiva con respecto a los últimos seis entradas, apenas mayor que el número de letras minúsculas, que es $26$, así que en ese caso no hay ninguna ventaja en particular a $33$. Eso es confirmado por los resultados experimentales que leonbloy vinculado a, donde a $31$ (con la etiqueta "K&R") incluso ligeramente mejor en las palabras de $33$ (con la etiqueta "Bernstein"); se puede ver cerca de la parte superior de la página o siguiendo las Bernstein vínculo que estos resultados se refieren al caso con la adición. (Esto es consistente con la idea de que los multiplicadores más bajos son generalmente mejor mientras mapa de las letras minúsculas injectively, pero parece arrojar algunas dudas sobre Ilmari del punto sobre el resto de mod $4$?)

Ejemplos en los que la combinación de $31$ y XOR no es inyectiva ya ocurre con $3$ letras; por ejemplo, "rox" y "rng" no se asignan a 1A607.

Esto es todo acerca de las ventajas de un multiplicador con respecto a la evitación de colisiones de hash. A menudo la velocidad de computación de la función de hash es al menos tan importante como evitar colisiones, y en ese sentido $33$ tiene la ventaja sobre la mayoría de los otros multiplicadores (aunque no más de $31$) que puede ser fácilmente calculada con un turno, y además, como usted ha explicado.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X