2009-03-25 140 views
18

Digamos que tengo un algoritmo hash, y es agradable y suave (las probabilidades de que surja un valor hash son las mismas que cualquier otro valor).¿Cómo calcular las probabilidades de una colisión en algoritmos hash?

Ahora digo que sé que las probabilidades de elegir 2 hashes y que haya una colisión son (por los argumentos) 50000: 1.

Ahora digo que recojo 100 hashes. ¿Cómo calculo las probabilidades de una colisión dentro de ese conjunto de 100 valores, dadas las probabilidades de una colisión en un conjunto de 2?

¿Cuál es la solución general a esto, por lo que puedo llegar a una serie de intentos de hash después de los cuales las probabilidades caen por debajo de un umbral aceptable? P.ej. Puedo decir cosas como "Un lote de creaciones de valor hash 49999 tiene una alta probabilidad de colisión".

+0

Un algoritmo hash perfecta es aquella donde no hay colisiones. Solo pensé en señalarlo. Disculpas por ser exigente :-) – CiscoIPPhone

+3

Suponiendo que el dominio de la función hash es mayor que el rango, eso es imposible. Si no es así, ¿por qué molestarse en usar un hash? – recursive

+2

Bueno, todavía obtiene la ventaja de velocidad de usar una función hash en lugar de buscar. http://en.wikipedia.org/wiki/Perfect_hash_function – CiscoIPPhone

Respuesta

1

Esto se llama the Birthday problem. Para resolverlo, piense en cambio en las probabilidades de que haya no colisiones (llámelo p nc).

  • p nc (1) = 1
  • p nc (2) = 1 - p c (2)
  • p nc (3) = P nc (2) * p nc (2) * p nc (2)
4

Eso me suena mucho al Birthday Paradox.

Debería poder simplemente sustituir el conjunto de posibles cumpleaños (365) con los posibles hash (50000) y ejecutar los mismos cálculos que allí se presentan.

Si modifica la secuencia de comandos de Python presenta en el artículo de sus valores:

def bp(n, d): 
    v = 1.0 
    for i in range(n): 

     v = v * (1 - float(i)/d) 
    return 1 - v 

print bp(2, 50000) 

Se termina con las probabilidades de colisión en dos números de 0,00002. Alrededor de 265 muestras, tiene alrededor de un 50% de posibilidades de tener una colisión.

+0

impresionante, gracias. – izb

+0

¿Es este un [puerto correcto] (http://codepad.org/7w2fXt02)? Obtuve 5.9 como la probabilidad. – Xeoncross

5

En primer lugar calcular la probabilidad de que no hay una colisión:

hashes_picked = 100 
single_collision_odds = 50000 

# safe_combinations is number of ways to pick hashes that don't overlap 
safe_combinations = factorial(single_collision_odds)/factorial(single_collision_odds - hashes_picked) 

# all_combinations is total number of ways to pick hashes 
all_combinations = single_collision_odds ** hashes_picked 

collision_chance = (all_combinations - safe_combinations)/all_combinations 
+0

¿Qué significa '**'? – Xeoncross

+1

Significa operador de potencia o exponente. '2 ** 3 == 8'. – recursive

0

y en JS

function calculate(n,k) 
{ 

    var result =1; 
    for (var i=0; i<k; i++){ 
     result=result*n/(n-i) 
    } 
    result=(1-1/result)*100; 
    return result; 
} 
Cuestiones relacionadas