単純な均一ハッシュを想定すると、つまり、任意の値は、ハッシュの任意のスロットにハッシュするのと同じようになります。 128ではなく127のサイズのテーブルを使用する方がよいのはなぜですか? 2の数の累乗の何が問題なのか本当にわかりません。または、それが実際にどのように違いを生むのか。
除算法を使用する場合、通常、m(テーブルサイズ)の特定の値を避けます。たとえば、mは2の累乗であってはなりません。これは、m = 2 ^ pの場合、h(k)はkのp個の最下位ビットにすぎないためです。
可能な要素が1から10000の間だけで、テーブルサイズを128として選択したとしましょう。127をどのように改善できるでしょうか。つまり、128は2 ^ 6(1000000)で、127は0111111です。これによってどのような違いが生じますか?すべての数値(ハッシュされた場合)は、127の場合でもkのp個の最下位ビットになります。私は何か間違ったことをしましたか?
なぜこれが悪いのか本当に理解できないので、いくつかの例を探しています。よろしくお願いします!
PS:私は知っています: ハッシュテーブル:なぜサイズがプライムでなければならないのですか?
すべての数値(ハッシュされた場合)は、127の場合でもkのp個の最下位ビットになります。
それは間違っています(または私は誤解しました..)。 k % 127
は、kのすべてのビットに依存します。 k % 128
最下位7ビットのみに依存します。
編集:
1から10,000の間の完全な分布がある場合。 10,000 % 127
および10,000 % 128
どちらも、これを優れた小さな分布に変えます。すべてのバケットには、10,000/128 = 78(または79)のアイテムが含まれます。
{x、2x、3x、..}がより頻繁に発生するため、偏った1から10,000までの分布がある場合。次に、この answer で説明するように、素数サイズははるかに優れた分布を提供します。 (xがまさにそのプライムサイズでない限り。)
したがって、(128のサイズを使用して)上位ビットを切り取るのは問題ありませんifif(-===-)下位ビットの分布で十分です。しかし、実際のデータと正しく設計されていないハッシュ関数では、これらの上位ビットが必要になります。
まず、素数を選ぶことではありません。たとえば、データセットが1〜10,000の範囲になることがわかっている場合、127または128を選択しても違いはありませんが、設計上の選択としては不適切です。
むしろ、例として3967のような非常に大きな素数を選択して、各データが独自の一意のキー/値のペアを持つようにすることをお勧めします。衝突も最小限に抑えたいだけです。例として127または128を選択しても、すべての127/128バケットが均一に満たされるため違いはありません(これは悪いことであり、挿入とルックアップの実行時間を低下させますO(1) to O(n)) 3967とは対照的(O(1)実行時間)
編集#4
「ハッシュ関数」のデザインはややブラックアートです。これは、ハッシュベースのデータ構造に格納されることを意図したデータの影響を強く受ける可能性があるため、賢明なハッシュ関数に関する議論は、特定の入力に関する議論に迷うことがよくあります。
素数が「推奨」される理由として、「敵対的な」分析を考慮する必要があります。つまり、私が一般的なハッシュベースのデータ構造を設計したとすると、敵からの最悪の入力が与えられた場合にどのように機能するでしょうか。パフォーマンスはハッシュ衝突によって決定されるため、問題は、最悪の条件での衝突を最小限に抑えるために使用するハッシュが何になるかです。そのような条件の1つは、入力が常に整数で割り切れる数値、たとえば4である場合です。N= 128を使用する場合、4 mod 128で割り切れる数値は4で割り切れます。つまり、バケット4、8、12、...のみです。 。は常に使用されるため、データ構造の使用率は25%になります。素数は、このようなシナリオが発生する可能性を効果的に減らします。
ニックは、一般的に、ハッシュテーブルのサイズは重要ではないということは正しいです。ただし、オープンアドレス法とダブルハッシュが使用される特別な場合(プローブ間の間隔は別のハッシュ関数によって計算されます)、素数サイズのハッシュテーブルすべてのハッシュテーブルエントリが新しい要素で使用できるようにするのが最善です(Corkscreeweが述べたように)。
ウィキペディアには実際にこれの良い要約があります:
http://en.wikipedia.org/wiki/Hash_table
彼らは、いくつかのハッシュ関数は素数でのみ動作するように設計されていると指摘しています。この記事では、2の累乗が悪い理由を説明します。
均等に分布している完全なハッシュ関数がある場合、それは問題ではありません。
100万年前の大学の試験でそうしなければならなかったことは覚えていますが、それを証明することはできませんが、最適なハッシュサイズは単なる素数ではありません。素数を選びたい[〜#〜] n [〜#〜]N = 4*M − 1
(ここで[〜#〜] m [〜#〜]も整数です)。
これにより、31は29よりもバケット数が多くなります。[〜#〜] m [〜#〜][〜#〜] n [〜#〜]の場合は8です。は31ですが、整数はありません[〜#〜] m [〜#〜][〜#〜] n [〜#〜]が29の場合。
私が言ったように、私はこれを証明する数学をもはや覚えていません。それは、約25年前、ウディの妻であるレイチェルマンバーによって教えられた理論コースでした。
「k%127はkのすべてのビットに依存します。k%128は下位7ビットにのみ依存します」を理解する方法は次のとおりです。 。
k%128はk&(2 ^ 7-1)に等しい。例:129%128 = 1、バイナリの場合:1000 0001&0111 1111 = 0000 0001、(2 ^ 7の任意の高さビット-1)は0になります。これは、高い位置が何であるかは関係ありません。ただし、この変換は2 ^ nに等しくない数値には無効です。
10進数の129%127で除算を行う方法を見てみましょう。最初に、127未満の最も高い位置1を見てから、次の項目2を拳と組み合わせて12を取得し、12は少なくなります。 127よりも、次に9と結合します。つまり、129を割り、127で割った余りは2です。これを数式で書くと、129 = 1 * 127 +2なので、2が得られます[これはすべて呼び出されます Long_division] 、そしてそれは2進除算でも同じです、今、私たちはk%127がkのすべてのビットに依存することを知っています
コンピュータが基数2で動作するという事実と関係があると私は信じています。基数10でも同様のことが起こります。
.。
2の累乗ではない十分な大きさの数値を選択すると、ハッシュ関数が実際にはすべての入力ビットのサブセットではなく、すべての入力ビットの関数であることが確認されます。
From なぜハッシュテーブルは素数サイズを使用すべきなのか 。