Применяется парадокс дня рождения : при наличии хорошей хеш-функции ожидаемое количество хешей до возникновения коллизии составляет около sqrt (N), где N - количество различных значений, которые может принять хеш-функция , (Запись в википедии, на которую я указал, дает точную формулу). Так, например, если вы хотите использовать не более 32 бит, ваши опасения коллизий серьезны для объектов размером около 64 КБ (т. Е. 2**16
объектов - квадратный корень из 2**32
различных значений, которые может принимать ваша хеш-функция) , Сколько объектов вы ожидаете иметь на порядок?
Поскольку вы упоминаете, что столкновение является незначительным раздражением, я рекомендую вам стремиться к длине хеша, которая примерно равна квадрату числа объектов, которое у вас будет, или немного меньше, но не НАМНОГО меньше этого значения.
Вы хотите создать имя файла - это в файловой системе, чувствительной к регистру, как в Unix, или вам также нужно обслуживать системы без учета регистра? Это важно, потому что вы стремитесь к коротким именам файлов, но количество бит на символ, которое вы можете использовать для представления своего хэша в качестве имени файла, резко меняется в системах с чувствительностью к регистру и против нечувствительных.
В чувствительной к регистру системе вы можете использовать модуль base64
стандартной библиотеки (я рекомендую версию кодировки urlsafe, т.е. эту функцию, чтобы избежать символов '/', которые могут присутствие в простом base64 важно в именах файлов Unix). Это дает вам 6 используемых бит на символ, что намного лучше, чем 4 бита / символ в шестнадцатеричном формате.
Даже в нечувствительной к регистру системе вы все равно можете работать лучше, чем в шестнадцатеричном формате - используйте base64.b32encode и получите 5 бит на символ.
Эти функции принимают и возвращают строки; используйте модуль struct
для преобразования чисел в строки, если выбранная вами хеш-функция генерирует числа.
Если у вас есть несколько десятков тысяч объектов, я думаю, вы будете в порядке со встроенным хешем (32 бита, поэтому 6-7 символов в зависимости от выбранной вами кодировки). Для миллиона объектов вы бы хотели 40 бит или около того (7 или 8 символов) - вы можете сложить (xor, не обрезать ;-) sha256 до длинного с разумным количеством бит, скажем, 128 или около того и используйте оператор %
, чтобы обрезать его до желаемой длины перед кодированием.