Я работаю с кодом, который вычисляет хэши списков объектов, алгоритм был взят из этого вопроса: Быстрый и простой Ха sh Кодовые комбинации . На основании второго ответа значения для seed и factor равны 1009 и 9176. Он хорошо работает для вычисления хэшей случайных списков целых чисел, но я обнаружил, что он просто не работает, когда списки похожи.
Если мы создадим список из 20 случайных целых чисел и вычислим га sh, используя:
int[] hashCodes = {
-1641555406,
1406166370,
431811193,
-719284004,
-463280747,
138136561,
-1634028130,
-792182888,
1325264708,
2143865166,
25622596,
-977152280,
1955313253,
-1440973864,
1627089736,
1733757615,
-576076691,
-145918914,
1015082677,
-954685337,
-1307289157
};
int hashCode = 1009;
foreach (var c in hashCodes)
hashCode = hashCode * 9176 + c;
И затем изменим только первое число:
hashCodes[0] = -145574454;
hashCode = 1009;
foreach (var c in hashCodes)
hashCode = hashCode * 9176 + c;
мы получим тот же код ha sh. Результат одинаков для любого случайного списка целых чисел - если отличается только первое число, мы получим один и тот же код ha sh около 8-10 итераций.
Я полагаю, что это из-за целочисленного переполнения и усекать старшие биты, но я не уверен. Я попытался использовать начальное число и коэффициент, основанный на первом ответе (17 и 31 соответственно), и он работал нормально. Это почему?
Как рассчитать такой ха sh (ха sh списка целых чисел)?
Редактировать: Согласно комментарию, это не криптографически безопасно, ха sh и не используется как таковой, это просто способ присвоить уникальный целочисленный ключ спискам целых чисел.