Вопрос теперь в том, нужно ли вам действительно случайное отображение или просто «слабая» перестановка. Предполагая последнее, если вы оперируете 32-разрядными целыми числами без знака (скажем) в арифметике дополнения 2, умножение на любое нечетное число является биективным и обратимым отображением. Конечно, то же самое относится и к XOR, поэтому вы можете попытаться использовать простой шаблон, например:
unsigned int hash(int x) {
return (((x ^ 0xf7f7f7f7) * 0x8364abf7) ^ 0xf00bf00b) * 0xf81bc437;
}
В числах нет ничего волшебного. Таким образом, вы можете изменить их, и они могут быть даже рандомизированы. Единственное, что мультипликаторы должны быть нечетными. И вы, должно быть, рассчитываете с помощью Rollaround (игнорируя переполнения). Это может быть перевернуто. Чтобы сделать инверсию, вы должны быть в состоянии вычислить правильные дополнительные мультипликаторы A и B, после чего инверсия равна
unsigned int rhash(int h) {
return (((x * B) ^ 0xf00bf00b) * A) ^ 0xf7f7f7f7;
}
Вы можете вычислить A и B математически, но вам проще всего запустить цикл и найти их (то есть в автономном режиме).
В уравнении используются XOR, смешанные с умножениями, чтобы сделать отображение нелинейным.