2009-02-13 3 views
15

Мне нужно хранить номера фиксированной длины (до 8 цифр), созданные из строк переменной длины. Хэш не обязательно должен быть уникальным. Это просто нужно изменить при изменении строки ввода. Есть ли хеш-функция в .Net, которая делает это?Числовой хэш-код фиксированной длины из строки переменной длины в C#

Thanks
Kishore.

ответ

20

Я предполагаю, что вы это делаете, потому что вам нужно сохранить значение в другом месте и сравнить с ним. Таким образом, ответ Заха (хотя и полностью правильный) может вызвать проблемы, поскольку контракт для String.GetHashCode() явно указывает на его возможности для изменения.

Таким образом, здесь фиксированная и легко повторяемая версия на других языках.

Я предполагаю, что во время компиляции вы будете знать количество десятичных цифр. Это основано на Jenkins One At Time Hash (как реализовано и exhaustively tested by Bret Mulvey), поэтому оно обладает отличным лавинным поведением (изменение одного бита на входе распространяется на все биты вывода), что означает несколько ленивая редукция по модулю в битах в конце концов, это не является серьезным недостатком для большинства применений (хотя вы могли бы сделать лучше с более сложным поведением)

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

В последней строке кода отсутствует код с запятой. Пытался отредактировать, но SO требует 6 изменений. –

6

Простой подход (обратите внимание, что это platform-dependent):

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

Это не будет оказывать такое же значение для двух разных строк с одинаковым содержимым – joshperry

+0

@ joshperry: Спасибо, я добавил отказ в ответе. –

+1

@joshperry - er, да, это будет .. просто не гарантировано останется неизменным между версиями .NET. Тем не менее, * no * hash может ** гарантировать ** изменить при изменении входного текста - столкновение, хотя и маловероятно, произойдет (очень, очень, очень редко). –

-1

System.Security.Cryptography.MD5CryptoServiceProvider.ComputeHash Используйте, чтобы получить хэш MD5, обрезать его до нужной длины.

Смежные вопросы