2009-02-13 16 views

Respuesta

20

Supongo que está haciendo esto porque necesita almacenar el valor en otro lugar y compararlo. Por lo tanto, la respuesta de Zach (aunque es completamente correcta) puede causarle problemas, ya que el contrato para String.GetHashCode() es explícito sobre su alcance para el cambio.

Por lo tanto, aquí hay una versión fija y fácilmente repetible en otros idiomas.

Supongo que sabrá en tiempo de compilación la cantidad de dígitos decimales disponibles. Esto se basa en Jenkins One At a Time Hash (implementado y exhaustively tested por Bret Mulvey), por lo que tiene un excelente comportamiento de avalancha (un cambio de un bit en la entrada se propaga a todos los bits de la salida) lo que significa algo reducción de módulo perezoso en bits al final no es un grave defecto para la mayoría de usos (aunque se podría hacer mejor con un comportamiento más complejo)

const int MUST_BE_LESS_THAN = 100000000; // 8 decimal digits 

public int GetStableHash(string s) 
{ 
    uint hash = 0; 
    // if you care this can be done much faster with unsafe 
    // using fixed char* reinterpreted as a byte* 
    foreach (byte b in System.Text.Encoding.Unicode.GetBytes(s)) 
    { 
     hash += b; 
     hash += (hash << 10); 
     hash ^= (hash >> 6);  
    } 
    // final avalanche 
    hash += (hash << 3); 
    hash ^= (hash >> 11); 
    hash += (hash << 15); 
    // helpfully we only want positive integer < MUST_BE_LESS_THAN 
    // so simple truncate cast is ok if not perfect 
    return (int)(hash % MUST_BE_LESS_THAN) 
} 
+0

Al código le falta un punto y coma en la última línea de código. Intentó editar, pero SO requiere 6 cambios. –

6

enfoque simple (tenga en cuenta que este es platform-dependent):

int shorthash = "test".GetHashCode() % 100000000; // 8 zeros 
if (shorthash < 0) shorthash *= -1; 
+0

esto no va a hacer que el mismo valor para dos cadenas diferentes con el mismo contenido – joshperry

+0

@ joshperry: Gracias, he agregado un descargo de responsabilidad en la respuesta. –

+1

@joshperry - er, sí ... no se garantiza que siga siendo el mismo entre las versiones de .NET. Sin embargo, * no * hash puede ** garantizar ** para cambiar cuando el texto de entrada cambia - las colisiones, aunque poco probable, sucederán (muy, muy, muy raramente). –

-1

Uso System.Security.Cryptography.MD5CryptoServiceProvider.ComputeHash para obtener un hash MD5, truncar a la longitud deseada.

Cuestiones relacionadas