2009-06-18 2 views
4

Я хочу, чтобы hash массив char в int или long. Полученное значение должно придерживаться заданного значения точности. Функция Я использую приводится ниже:String to Integer Hashing Function with Precision

int GetHash(const char* zKey, int iPrecision /*= 6*/) 
{ 
     /////FROM : http://courses.cs.vt.edu/~cs2604/spring02/Projects/4/elfhash.cpp 

     unsigned long h = 0; 
     long M = pow(10, iPrecision); 

     while(*zKey) 
     { 
       h = (h << 4) + *zKey++; 
       unsigned long g = h & 0xF0000000L; 
       if (g) h ^= g >> 24; 
       h &= ~g; 
     }    

     return (int) (h % M); 
} 

Строка хешироваться похожа на «SAEUI1210.00000010_1».

Однако в некоторых случаях это создает повторяющиеся значения. Есть ли хорошие альтернативы, которые не будут дублировать один и тот же хэш для разных строковых значений.

+0

Попробуйте использовать CRC 32: http://en.wikipedia.org/wiki/Crc32 –

ответ

13

Само определение хэша состоит в том, что оно создает повторяющиеся значения для некоторых значений из-за того, что диапазон значений хеширования меньше, чем пространство хешированных данных.

Теоретически, 32-битный хэш имеет достаточный диапазон для хэша всех ~ 6 символьных строк (только A-Z, a-z, 0-9), не вызывая столкновения. На практике хеши не являются идеальной перестановкой входных данных. Учитывая 32-битный хеш, вы можете ожидать получить хэш-коллизии после хэширования ~ 16 бит случайных входов, из-за birthday paradox.

Учитывая статический набор значений данных, всегда можно построить хеш-функцию, созданную специально для них, которая никогда не столкнется с самим собой (конечно, размер ее выхода будет не менее log(|data set|). Однако это требует от вас знать все возможные значения данных раньше времени. Это называется perfect hashing.

Это, как говорится, here несколько альтернатив, которые должны получить вы начали (они предназначены для уменьшения коллизий)

+0

Какая лучшая функция хеширования использовать из тех, которые указаны в предоставленной вами ссылке, и той, которую я использую прямо сейчас. Функция, которую я использую, кажется более сложной, чем djb2 и sdbm. Означает ли это, что лучше избегать столкновений? – Gayan

+0

Единственный способ проверить, какая хэш-функция является «наилучшей» для ваших целей, - это выполнить контрольный образец для образца данных, который соответствует вашим ожидаемым реальным данным. Функция, которую вы используете, не пытается слишком сильно смешивать входные биты, чтобы создать хэш - на каждом шаге смешиваются не более 4 верхних бит; и в строках длиной <8, даже этого не происходит, ваш хеш просто накапливает все символы с небольшим перекрытием. – ASk

2

Каждый хэш будет иметь столкновения. Период. Это называется Birthday Problem.

Возможно, вы захотите проверить наличие криптографических функций, таких как MD5 (относительно быстро, и вам все равно, что это небезопасно), но также будут иметь коллизии.

+0

Идеальные хэши по определению нет. – MSalters

2

Хэши генерировать тот же значение для разных входов - вот что они делают. Все, что вы можете сделать, это создать хеш-функцию с достаточным распределением (или оба) для минимизации этих столкновений. Поскольку у вас есть это дополнительное ограничение точности (0-5?), Вы будете чаще сталкиваться с столкновениями.

1

MD5 или SHA. Существует много открытых реализаций, и результат вряд ли приведет к дублированию результатов.

+0

Да. Но мое требование также включает в себя тот факт, что результат должен быть целым числом. Хеши MD5 содержат как ints, так и символы. Я думаю, что это так же для алгоритмов SHA. – Gayan

+0

Правда, но преобразование тривиально - от 128 бит до 32-битного целого. Вы получите код с двумя строками (хеш, int-преобразование), который создает де-факто отсутствие хэша конфликтов. –