Efective способ избежать целочисленного переполнения при умножении?

Я работаю над хеш-функцией, которая получает строку, как введено.

Прямо сейчас я делаю цикл, и в хеше (международная переменная) умножается на значение, и затем код ASCII для текущего символа добавляется к соединению.

hash = hash * seed + string[i]

Но иногда, если строка является достаточно большой, там существует целочисленное переполнение, что я могу сделать для предотвращения его при поддержании той же структуры хеша? Возможно, немного операции, включенной в цикле?

1
задан Jonathan 4 May 2010 в 19:02
поделиться

4 ответа

Почему бы не использовать long для хранения результата? Затем вы можете применить методы такие как этот для обнаружения переполнения

0
ответ дан 3 September 2019 в 00:47
поделиться

Если у вас есть доступ к большему типу данных, вы можете сделать что-то вроде этого:

int32_t hash, seed;
int64_t temporary;

temporary = hash * seed + string[i];
hash = ( temporary >> 32 ) ^ ( temporary & 0xFFFFFFFF );

В противном случае вам придется вручную размножить хэш и seed на два значения, добавить string[i] с переполнением, а затем ^ эти два значения.

Хеши неявно несут потери, поэтому можно просто оставить биты переполнения, если только нет конкретной причины, по которой они нужны, например, для соответствия существующему алгоритму.

0
ответ дан 3 September 2019 в 00:47
поделиться

Существует несколько возможных интерпретаций вашего вопроса, и, как отмечено в комментариях, вам может потребоваться пояснение.

Однако единственная разумная интерпретация состоит в том, что вы хотите ограничить значение хеш-функции определенным диапазоном. Предполагая, что тогда, если бы диапазон был от 0 до HASH_TABLE_SIZE - 1, тогда:

hash = (hash * seed + string[i]) % HASH_TABLE_SIZE ;

или если размер таблицы является степенью двойки, используйте маску:

#define HASH_TABLE_SIZE (0x01<<8)  // 2^8 (256) table
#define HASH_MODULO_MASK (HASH_TABLE_SIZE - 1)
...
hash = (hash * seed + string[i]) & HASH_MODULO_MASK ;
1
ответ дан 3 September 2019 в 00:47
поделиться

Хеш-функции, подобные этой, должны переполняться. Вы должны объявить "хэш" без знака. Если вам действительно нужен int, просто используйте hash & 0x7fffffff. Просмотрите алгоритм Фаулера-Нолля-Во , вы найдете там ссылки на исходный код.

1
ответ дан 3 September 2019 в 00:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: