partir de la información vista teórico, que tienen 2^64
valores para trazar un mapa en 2^63-1
valores.
Como tal, la cartografía es trivial con el operador módulo, ya que siempre tiene un resultado no negativo:
y = 1 + x % 0x7fffffffffffffff; // the constant is 2^63-1
Esto podría ser bastante caro, así que ¿qué más es posible?
La matemática simple 2^64 = 2 * (2^63 - 1) + 2
dice que tendremos dos mapeos de valores de fuente a un valor objetivo excepto en dos casos especiales, donde tres irán a uno. Piense en estos dos valores especiales de 64 bits, llámelos x1
y x2
, que comparten un objetivo con otros dos valores fuente. En la expresión anterior mod
, esto ocurre al "envolver". Los valores objetivo y=2^31-2
y y=2^31-3
tienen tres asignaciones. Todos los demás tienen dos.Dado que tenemos que usar algo más complejo que mod
de todos modos, busquemos una forma de asignar los valores especiales donde queramos a bajo costo
Para la ilustración vamos a trabajar con el mapeo de un intde 4 bits en [-8 .. 7] a y
en [1..7], en lugar del espacio de 64 bits.
un curso fácil es tener x
valores en el mapa [1..7] a sí mismos, entonces el problema se reduce a la cartografía de x
en [-8..0] para y
en [1..7]. Tenga en cuenta que hay 9 valores de origen aquí y solo 7 objetivos como se discutió anteriormente.
Existen obviamente muchas estrategias. En este punto, probablemente puedas ver un gazzilion. Describiré solo uno que es particularmente simple.
Deje y = 1 - x
para todos los valores excepto casos especiales x1 == -8
y x2 == -7
. La función hash entera se convierte así en
y = x <= -7 ? S(x) : x <= 0 ? 1 - x : x;
Aquí S(x)
es una función simple que dice donde x1
y x2
se asignan. Elija S
según lo que sabe sobre los datos. Por ejemplo, si cree que los valores de objetivo altos son poco probables, identifíquelos en 6 y 7 con S(x) = -1 - x
.
La asignación final es:
-8: 7 -7: 6 -6: 7 -5: 6 -4: 5 -3: 4 -2: 3 -1: 2
0: 1 1: 1 2: 2 3: 3 4: 4 5: 5 6: 6 7: 7
Tomando esta lógica hasta el espacio de 64 bits, que tendría
y = (x <= Long.MIN_VALUE + 1) ? -1 - x : x <= 0 ? 1 - x : x;
Muchos otros tipos de afinación son posibles dentro de este marco.
No, el codominio hash es mucho más - pero debe ser> 0. Voy a actualizar el post para hacerla más precisa. – eold
Tenga en cuenta que en el ejemplo "feo" 0 colisiona con 7. – Hounshell
El ejemplo "feo" asigna MIN_VALOR a 0. Y obtener 0 no es bueno. –