Является ли эта хэш-функция уникальной?

Будет ли следующий сгенерированный хэш всегда отличаться для разных ключей, при условии, что целое число хеша никогда не переполняется? Ключ должен содержать символы в кодировке ascii.

Я думаю, что это так, поскольку я не могу думать об исключительном случае.

char[] arr = "abcd"
int hash = 0
for (int i=0; i<arr.size; i++) {
    hash += (i+1) * arr[i]
}

EDIT1: Хотя нижеприведенные ответы являются технически правильными ответами на мой первоначальный вопрос, я должен был упомянуть, что домен ключей — это домен действительных идентификаторов электронной почты. Таким образом, некоторые символы ascii не включены. Тем не менее, я проведу некоторые тесты и отчитаюсь. Единственная проблема в том, что перечислить все перманенты можно только до небольшой длины.

В любом случае, мое требование состоит в том, чтобы создавать уникальные идентификаторы на основе идентификаторов электронной почты и использовать их в качестве первичных ключей в базе данных. Просто не хотите использовать сами почтовые идентификаторы.

EDIT2: Хорошо, по-видимому, есть множество столкновений. например, хэш [email protected] == хэш [email protected]

...
040 == 012
041 == 013
042 == 014
043 == 015
044 == 016
045 == 017
046 == 018
047 == 019
048 == 01:
...

Мне нужен другой алгоритм хеширования. Можете ли вы предложить любой?


person DebD    schedule 04.08.2016    source источник
comment
Будет ли следующий сгенерированный хеш всегда отличаться для разных ключей? По определению хеш-функции ответ - нет. Если ответ положительный, не называйте это хэш-функцией.   -  person John Coleman    schedule 04.08.2016
comment
вы берете большое пространство значений и сжимаете его до меньшего пространства. по определению БУДЕТ быть как минимум 2 входных значения, которые сопоставляются с одним и тем же выходом.   -  person Marc B    schedule 04.08.2016
comment
Должно быть хотя бы одно столкновение   -  person xdevs23    schedule 04.08.2016


Ответы (3)


Нет: например, 1*2 + 2*2 = 1*4 + 2*1.

(char[] arr = {'\u0002','\u0002'} и char[] arr = {'\u0004','\u0001'})

person Gábor Bakos    schedule 04.08.2016

Эти две строки будут генерировать идентичные хэши:

"~ "
"@?"

Вышеупомянутое полностью состоит из печатных символов ASCII.

Грубым способом проверки вашего алгоритма было бы просто попробовать все комбинации из 2 символов, а затем, возможно, все комбинации из 3 или 4 символов, чтобы получить представление об уникальности.

char key[5] = {0};
bool used[65536] = {0};
for (key[0] = " "; key[0] < 128; key[0]++)
    for (key[1] = " "; key[1] < 128; key[1]++) {
        if (used[hashcode(key)]) {
            printf("failed %s", key);
        else
            used[hashcode(key) = true;
        }
person roderick young    schedule 04.08.2016
comment
Два упомянутых вами значения дают 190 и 253 соответственно. - person DebD; 04.08.2016
comment
Ой, извини @DebD. Я думаю, это должно быть - person roderick young; 05.08.2016
comment
Хороший улов, @DebD. Я плохо отношусь к тому, что не проверил внимательно таблицу ASCII перед вводом текста, должно быть, я прочитал восьмеричное значение или что-то в этом роде. Попробую второй поправить на @? вместо ошибочного {A - person roderick young; 05.08.2016

Отвечая на ваш дополнительный вопрос в вашем редактировании о стремлении улучшить вашу хэш-функцию, небольшое изменение, которое вы могли бы внести, состояло бы в том, чтобы умножить каждый символ на простое число перед добавлением к общему количеству. Это не гарантирует отсутствие столкновений, но должно сократить их, так как каждый новый добавляемый термин будет разнесен на большее расстояние и будет кратен простому числу. Я бы пропустил первые несколько простых чисел, чтобы получить лучший интервал, поэтому, возможно, умножьте первый символ на 11, второй на 13, третий на 17, 4-й на 19 и так далее. Если ваши строки не слишком длинные, вам не понадобится очень большая таблица простых чисел.

Если вы действительно хотите пофантазировать, вы можете изучить генерацию CRC или использовать технику регистра сдвига с линейной обратной связью для генерации подписи. В последнем случае вы выполняете XOR нового символа (или выбранных битов нового символа) в младших 8 битах промежуточной суммы, а затем вращаете всю сумму на определенное количество битов.

person roderick young    schedule 05.08.2016