Если безопасность не имеет значения, то, что вы описываете, на мой взгляд, не хеш-функция.Хеш-функция - это односторонняя функция, означающая, что вычисление хеш-функции легко, но отменить его «сложно» или, в идеале, невозможно.
Вместо этого ваши требования описывают инъективную функцию x1, x2 в вашем домене X имеет место следующее:
For all x1, x2 element of X, x1 != x2 => f(x1) != f(x2)
f (x) = x - это такая функция, f (x) = x² нет.Говоря простым языком: вы хотите получить разные результаты, если ваши входные данные разные, такие же результаты, только если входные данные совпадают.Это правда, что это также верно для безопасных хэшей, но они дополнительно обеспечивают односторонние характеристики, такие как свойство неспособности (легко) найти x, если вам дано только f (x), среди других.Насколько я понял, вам не нужны эти свойства безопасности.
Тривиально, такое инъективное отображение из String в Float будет дано просто интерпретацией «String bytes» как «Float bytes» с этого момента.то есть вы интерпретируете байты по-разному (подумайте C:
unsigned char *bytes = "...";
double d = (double)bytes;
).Но есть и обратная сторона этого - реальная проблема в том, что Float имеет максимальную точность, поэтому вы столкнетесь с ситуацией переполнения, если ваши строки слишком длинные (Float внутренне представлены как значения double
, это 8 байт на32 битная машина).Так что не хватает места практически для любого варианта использования.Даже MD5 - сначала ваши строки не решают проблему - вывод MD5 уже имеет длину 16 байт.
Так что это может быть реальной проблемой, в зависимости от ваших точных требований.Хотя MD5 (или любой другой хэш) будет достаточно путаться со входными данными, чтобы сделать его как можно более случайным, вы все равно сократите диапазон возможных значений с 16 байтов до фактически 8 байтов.(Примечание: усечение случайного 16-байтового вывода при 8 байтах обычно считается «безопасным» с точки зрения сохранения случайности. Криптография с эллиптической кривой делает нечто подобное. Но, насколько я знаю, никто не может доказать это, но никто не может доказатьнаоборот пока).Таким образом, столкновение намного более вероятно с вашим ограниченным диапазоном Float.По парадоксу дня рождения, нахождение коллизии занимает sqrt (количество значений в конечном диапазоне).Для MD5 это 2 ^ 64, но для вашей схемы это всего 2 ^ 32.Это все еще очень, очень маловероятно, чтобы вызвать столкновение.Вероятно, это что-то в порядке выигрыша в лотерею и в то же время удар молнии.Если бы вы могли жить с этой минимальной возможностью, сделайте это:
def string_to_float(str)
Digest::MD5.new.digest(str).unpack('D')
end
Если уникальность имеет абсолютный приоритет, я бы рекомендовал перейти от чисел с плавающей точкой к целым числам.Ruby имеет встроенную поддержку больших целых чисел, которые не ограничены внутренними ограничениями значения long
(это то, к чему сводится Fixnum).Таким образом, любой произвольный вывод хеша может быть представлен как большое целое число.