入力を広げる機能


14

次の特性を持つnビット数からnビット数までの関数があるかどうかを知りたいf:

  • fは全単射で必要があります
  • 両方の及び計算可能かなり高速であるべきですff−1
  • fは、入力と有意な相関関係のない数値を返す必要があります。

その理由は次のとおりです。

データを操作するプログラムを書きたい。データの一部の情報は、検索キーがアルファベットの記号であるバイナリ検索ツリーに保存されます。時間とともに、アルファベットにさらに記号を追加します。新しいシンボルは、利用可能な次の無料番号を取得するだけです。したがって、ツリーは常に小さなキーに対して小さなバイアスを持ち、必要以上にリバランスが発生します。

私のアイデアは、シンボル番号を範囲全体に広く広がるようにマングルすることです。シンボル番号は、一度だけ発生する入出力中にのみ重要であるため、このような関数を適用することはそれほど高価ではありません。f[0,264−1]

Xorshift乱数ジェネレーターの1つの反復について考えましたが、理論的には可能であるはずですが、元に戻す方法は実際にはわかりません。

誰もがそのような機能を知っていますか?
これはいいアイデアですか?


1
(例えば参照私は専門家ではないんだけど、おそらくあなたは、擬似ランダム置換を使用することができたFeistel暗号を)
— はVor

本質的にハッシュ関数を計算している場合、ハッシュを使用しないのはなぜですか?
— フォンブランド

@vonbrand Hashingは元に戻せません。要件番号2を参照してください
— 。– FUZxxl

なぜ可逆的でなければならないのですか?ルックアップによって元に戻すことの何が問題になっていますか?
— フォンブランド

1
(f(x)、x)をキーとして保存できます。
— -adrianN

回答:


6

フィボナッチハッシュを使用することができます、すなわち

。hF(k)=k⋅5−12−⌊k⋅5−12⌋

以下のためあなたが得るのnペアワイズ、明確な数字は(約)に均等に広がって、[ 0 、1 ]。[ 1 .. M ]にスケーリングし、切り捨て(切り捨て)を行うと、その間隔で数値が均等に広がります。k=1、…、nn[0、1][1 ..M]

たとえば、これらは [ 0..10000 ]にスケーリングされた h F(1 )、… 、h F(200 )です(左の元のシーケンス、右にソート):hF(1)、…、hF(200)[0..10000]

ここに画像の説明を入力してください

これは、Knuthが乗法ハッシュと呼ぶもののインスタンスです。以下のための、コンピュータのワードサイズ、Aにはいくつかの整数互いに素ワットとM必要なアドレスの数、我々が使用しますwAwM

h(k)=⌊M((k⋅Aw)モッド1)⌋

ハッシュ関数として。上記はA / w = ϕ − 1 = √で続きます(十分な精度で計算できることを確認してください)。これはϕ−1以外の他の無理数でも機能しますが、「最も均一に分布した」数につながるのは2つの数のうちの1つです。A/w=ϕ−1=5−12ϕ−1

詳細については、Donald KnuthによるThe Art of Computer Programming Volume 3を参照してください(第2版の513ページの6.4章)。結果の数字は(ペアごとに区別される理由は特に、あなたは見つけることができます少なくとも、もしn≪M)とどのように自然な使用している場合は逆関数を計算するためにとワットの代わりに、φ - 1。Awϕ−1


1
f − 1の計算方法f−1効率的?
— frafl

1
@frafl私の編集があなたの懸念にいくらか対処することを願っています。ただし、これらのハッシュ手法が効率的に可逆になるように特に設計されていないことは明らかです。
— ラファエル

はい、私は賛成しますが、受け入れられた答えとしてはお勧めしません。
— frafl

1

以下のためビット入力、この機能は動作します:k

hash(n)=(nモッド2⌈k2⌉)⋅2⌈k2⌉+nd私v2⌈k2⌉

これは可逆であり、であり、非順次ペア{ n 、m } 、n < mを持ち、ここでh a s h(m )< h a s h(n )。特に入力が{ 1 、… にある場合、出力と入力が相関する可能性があることに注意してくださいhash(hash(n))=n{n,m},n<mhash(m)<hash(n)。{1,…,2⌈k2⌉−1}

参照:可逆ハッシュ関数


これはシンプルで素敵に見えます。私はそれをテストするつもりです。
— -FUZxxl

1
1.入力によっては、強い相関が生じる場合があります(スピアマンのρの場合は最大)2.これは64ビットではなく32ビットです3.言語に依存しない方法でこれを書いていただけますか?1ρ
— frafl

かなり明確です!64ビット(0x00000000FFFFFFFF)の場合、32ビットをシフト(<<)する必要があります。この機能はシンプルで実用的で、実際には十分高速です。
— レザ

1
しかし、なぜあなたは、それがすべてのマッピングされていないビットの順列を使用していないの2 32のx?前述のように、これは明らかにOPが要求する相関条件に違反しています。バツ∈{1、…、232−1}232バツ
— frafl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.