Я ищу алгоритм постоянного времени, который может изменить значение упорядоченного целочисленного индекса на случайный хеш-индекс. Было бы неплохо, если бы он был обратимым. Мне нужно, чтобы хеш-ключ был уникальным для каждого индекса. Я знаю, что это можно сделать, просмотрев таблицу в большом файле. I.E. создать упорядоченный набор всех целых чисел, а затем перемешать их случайным образом и записать в файл в случайной последовательности. Затем вы можете прочитать их, когда они вам понадобятся. Но для этого потребуется поиск в большом файле. Интересно, есть ли простой способ использовать, скажем, псевдослучайный генератор для создания последовательности по мере необходимости?
Генерация перемешанного диапазона с использованием ГПСЧ вместо перемешивания ответ от erikkallen из регистров сдвига с линейной обратной связью выглядит правильным. Я только что пробовал, но он дает повторы и дыры.
С уважением, Дэвид Аллан Финч
5 ответов
Вопрос теперь в том, нужно ли вам действительно случайное отображение или просто «слабая» перестановка. Предполагая последнее, если вы работаете с 32-битными целыми числами без знака (скажем) в арифметике дополнения до 2, умножение на любое нечетное число является биективным и обратимым отображением. Конечно, то же самое касается XOR, поэтому простой шаблон, который вы можете попробовать использовать, например,
unsigned int hash(int x) {
return (((x ^ 0xf7f7f7f7) * 0x8364abf7) ^ 0xf00bf00b) * 0xf81bc437;
}
В цифрах нет ничего волшебного. Таким образом, вы можете изменить их, и они могут быть даже рандомизированы. Единственное, множимые должны быть нечетными. И вы должны выполнять вычисления с откатом (без учета переполнения). Это можно перевернуть. Чтобы выполнить инверсию, вы должны быть в состоянии вычислить правильные дополнительные множимые A и B, после чего инверсия будет
unsigned int rhash(int h) {
return (((x * B) ^ 0xf00bf00b) * A) ^ 0xf7f7f7f7;
}
Вы можете вычислить A и B математически, но для вас проще просто запустить цикл и найти их (то есть в автономном режиме).
Уравнение использует операции XOR, смешанные с умножениями, чтобы сделать отображение нелинейным.
Вы можете попробовать создать подходящую сеть Фейстеля. Обычно они используются для криптографии (например, DES), но имеют как минимум 64 бита, поэтому вам может потребоваться создать такой, который соответствует вашим потребностям. По построению они обратимы.
Предполагая, что ваша цель - распределить сгруппированные значения по всему диапазону,
похоже, что перетасовка битов в каком-то заранее определенном порядке может помочь.
т.е. учитывая 8 бит ABCDEFGH, расположите их как EGDBHCFA или какой-то такой шаблон.
Код будет простой последовательностью масок, сдвигов и добавлений.
Ммм ... в зависимости от того, много ли у вас чисел, вы можете использовать обычный список stl и упорядочить его по "случайным" критериям
bool
nonsort(int i, int j)
{
return random() & 31 >16 ? true : false;
}
std::list<int> li;
// insert elements
li.sort(nonsort);
Затем вы можете получить все целые числа с помощью обычного итератора. Не забудьте инициализировать random с помощью srand () временем или любым другим псевдослучайным значением.
Для набора ограничений действительно нет решения. Попытка хешировать 32-битное беззнаковое в 32-битное беззнаковое приведет к коллизиям, если вы не сделаете что-то простое, например, сопоставление 1 к 1. Каждое число - это свой хэш.
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .