情報理論の観点から、2^64
値にマッピングする2^63-1
値があります。
そのため、モジュラス演算子を使用したマッピングは、常に非負の結果になるため、自明です。
y = 1 + x % 0x7fffffffffffffff; // the constant is 2^63-1
これはかなり高価になる可能性があるので、他に何が可能ですか?
簡単な計算2^64 = 2 * (2^63 - 1) + 2
では、2 つのソース値が 1 つのターゲット値にマッピングされることになりますが、2 つの特殊なケース (3 つが 1 つになる) を除きます。これらを 2 つの特別な 64 ビット値と考えて、x1
と と呼びx2
、それぞれが他の 2 つのソース値とターゲットを共有します。上記のmod
式では、これは「ラッピング」によって発生します。ターゲット値y=2^31-2
にy=2^31-3
は 3 つのマッピングがあります。他はすべて2つです。とにかくもっと複雑なものを使わなければならないのでmod
、低コストで好きな場所に特別な値をマッピングする方法を探しましょう
説明のために、[-8..7] の 4 ビット符号付き intを64 ビット空間ではなく x
[1..7] にマッピングしてみましょう。y
簡単なコースは、[1..7]x
の値をそれ自体にマップすることです。その後、問題x
は [-8..0] の [1..7] へのマッピングに縮小されy
ます。上記のように、ここには 9 つのソース値があり、ターゲットは 7 つしかないことに注意してください。
明らかに多くの戦略があります。この時点で、おそらくガジリオンを見ることができます。特に簡単なものを 1 つだけ説明します。
y = 1 - x
特殊なケースを除くすべての値をみましょうx1 == -8
およびx2 == -7
. したがって、ハッシュ関数全体は次のようになります
y = x <= -7 ? S(x) : x <= 0 ? 1 - x : x;
以下は、とがマップされS(x)
ている場所を示す単純な関数です。データについて知っていることに基づいて選択します。たとえば、目標値が高い可能性が低いと思われる場合は、 を使用してそれらを 6 と 7 にマッピングします。x1
x2
S
S(x) = -1 - x
最終的なマッピングは次のとおりです。
-8: 7 -7: 6 -6: 7 -5: 6 -4: 5 -3: 4 -2: 3 -1: 2
0: 1 1: 1 2: 2 3: 3 4: 4 5: 5 6: 6 7: 7
このロジックを 64 ビット空間にすると、次のようになります。
y = (x <= Long.MIN_VALUE + 1) ? -1 - x : x <= 0 ? 1 - x : x;
このフレームワーク内では、他にも多くの種類のチューニングが可能です。