2017-02-21 47 views
2

Я пытаюсь создать функцию, которая генерирует хэш-ключ, основанный на том, где в хеш-таблице я хочу, чтобы значение было выполнено.Как изменить функцию хеша-метода

My hash function is (a + b * (key)) % c = hash value. Я видел similar question к этому на SO, и то, что я пытался замену b * (key) с d и просто делать:

private int ReverseModulus(int a, int b, int c, int hashValue) 
{ 
    if(hashValue >= c) 
     return -1; 
    if(a < hashValue) 
     return (hashValue - a)/b; 
    return (c + hashValue - a)/b; 
} 

но мне кажется, что большую часть времени hashValue != Hash(ReverseModulus(a,b,c, hashValue)).

Мне было интересно, неправильный подход или если в коде есть только ошибка.

+7

Хеши, по дизайну, в одну сторону. – Servy

+0

Я думаю, что вы хотите прочитать [Perfect Hash Function] (https://en.wikipedia.org/wiki/Perfect_hash_function) –

+0

Я знаю, что между ключами и значениями хэша нет взаимно однозначных отношений, но я просто хочу чтобы получить одно из бесконечного числа ключей, которые будут генерировать желаемое значение хэш-функции. Например, вы можете переборщить его, итерации от 0 до тех пор, пока не получите правильное значение хэш-функции. –

ответ

0

Вы используете неправильный тип деления. Вы выполняете целочисленное деление, но вам нужно делать модульное деление. В Java вы можете использовать BigInteger:

bh = new BigInteger(hashValue); 
ba = new BigInteger(a); 
bc = new BigInteger(c); 
bn = bh.subtract(ba); 
return bn.modInverse(bc).intValue(); 

и C# предположительно имеет аналогичные функции библиотеки.

+1

Не должно быть' bn.multiply (bb.modInverse (bc)) '? Кроме того, вам нужно использовать 'BigInteger.valueOf()', а не 'new BigInteger()'. Наконец, инверсия мультипликатора должна быть константой, и все это выполняется как «арифметика int» для эффективности: return (h - a) * B_INV; ' – erickson

+0

@erickson Я только что протестировал ваше предложение, и оно работает. Просто любопытно, что означает 'B_INV'? –

+1

@Jedi_Maseter_Sam 'B_INV' является мультипликативным обратным к' b', по модулю 'c'. Я предполагаю, что 'c' составляет 2^32, но если это не так, вам просто потребуется одна дополнительная операция вместо того, чтобы полагаться на арифметическое переполнение' int'. Вы получаете 1, если умножить 'b' и' B_INV', по модулю 'c'. Вы можете вычислить 'B_INV' как' BigInteger bb = BigInteger.valueOf (b), bc = BigInteger.valueOf (c); int B_INV = bb.modInverse (bc) .intValue(); 'Делайте это, когда ваша программа запускается, или соответствующий класс инициализируется, или даже вычисляет его и записывает в вашу программу. Затем вы можете сэкономить ненужные расходы BigInteger. – erickson