Функція, яка поширює вхід


14

Мені хотілося б знати, чи існує функція f від n-бітних чисел до n-розрядних чисел, яка має такі характеристики:

  • f має бути біективним
  • І f і f1 повинні бути обчислені досить швидко
  • f повинен повернути число, яке не має суттєвої кореляції з його введенням.

Обґрунтування таке:

Я хочу написати програму, яка працює на даних. Деяка інформація даних зберігається у двійковому дереві пошуку, де ключ пошуку є символом алфавіту. З часом я додаю ще символи до алфавіту. Нові символи просто отримують наступний вільний номер. Отже, дерево завжди матиме невеликий ухил до менших клавіш, що спричиняє більше балансування, ніж я вважаю, що потрібно.

Моя ідея полягає в тому, щоб перемацати числа символів f таким чином, щоб вони були широко розповсюджені у всьому діапазоні [0,2641] . Оскільки номери символів мають значення лише під час введення та виведення, що відбувається лише один раз, застосування такої функції не повинно бути занадто дорогим.

Я думав про одну ітерацію генератора випадкових чисел Xorshift, але насправді не знаю способу його скасувати, хоча теоретично це повинно бути можливим.

Хтось знає таку функцію?
Це гарна ідея?


1
Я не фахівець, але, можливо, ви можете використовувати псевдовипадкову перестановку (див., Наприклад, шифр Feistel )
Vor

Якщо ви по суті обчислюєте хеш-функцію, чому б не використовувати хешування?
vonbrand

@vonbrand Хешинг не є оборотним. Дивіться вимогу № 2.
FUZxxl

Чому він повинен бути оборотним? Що не так у тому, щоб зробити його зворотним шляхом пошуку?
фонбранд

1
Ви можете зберігати (f (x), x) як клавіші.
adrianN

Відповіді:


6

Ви можете використовувати хешування Фібоначчі , а саме

.hF(k)=k512k512

Для ви отримуєте n парних чисел (приблизно), рівномірно розподілених у [ 0 , 1 ] . Шляхом масштабування доk=1,,nn[0,1] і округлюючи (вниз), ви отримуєте приблизно рівномірно розподілені числа в цьому інтервалі.[1..M]

Наприклад, це масштабований до [hF(1),,hF(200) (ліва вихідна послідовність, право відсортовано):[0..10000]

введіть тут опис зображення

Це приклад того, що Кнут називає мультиплікативним хешированием . Для розмір слова комп'ютера, А деяке ціле число , взаємно просте з ш іwAw кількість адреснеобхідних, ми використовуємоM

h(k)=M((kAw)mod1)

як функція хешування. Сказане випливає з (переконайтеся, що ви можете обчислити його з достатньою точністю). Хоча це також працює з будь-яким іншим ірраціональним числом, крімϕA/w=ϕ1=512 , це одне з лише двох чисел, що призводять до "найбільш рівномірно розподілених" чисел.ϕ1

Докладніше в «Мистецтві комп’ютерного програмування» , Том 3 Дональда Кнута (глава 6.4 зі сторінки 513 у другому виданні). Зокрема, ви дізнаєтеся, чому отримані числа попарно відрізняються (принаймні, якщо ) і як обчислити зворотну функцію, якщо ви використовуєте натуральні A і w замість ϕ - 1 .nMAwϕ1


1
Як обчислити ефективно? f1
frafl

1
@frafl Я сподіваюся, що моя редакція дещо вирішує вашу проблему. Зрозуміло, однак, що ці методи хешування не є спеціально розробленими для того, щоб бути ефективно оберненими.
Рафаель

Так, це є, я підтримаю його, проте я б не рекомендував це як прийняту відповідь.
frafl

1

Для бітових входів ця функція працює:k

hash(n)=(nmod2k2)2k2+ndiv2k2

hash(hash(n))=n{n,m},n<mhash(m)<hash(n){1,,2k21}

Посилання: Оборотна хеш-функція


Це виглядає просто і приємно. Я збираюся перевірити це.
FUZxxl

1
1ρ

це досить зрозуміло! для 64-розрядних (0x00000000FFFFFFFF) і вам слід змістити (<<) 32 біти. Ця функція проста, практична і досить швидка на практиці.
Реза

1
x{1,,2321}232x
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.