web-dev-qa-db-ja.com

Tuple(set([1、 "a"、 "b"、 "c"、 "z"、 "f"]))== Tuple(set(["a"、 "b"、 "c"、 "z"、 "f"、1]))ハッシュランダム化が有効になっている場合の85%

別の質問に対するゼロピレウスの答え 、私たちはそれを持っています

x = Tuple(set([1, "a", "b", "c", "z", "f"]))
y = Tuple(set(["a", "b", "c", "z", "f", 1]))
print(x == y)

ハッシュランダム化 を有効にすると、Trueの約85%の時間を出力します。なぜ85%ですか?

97
Veedrac

この質問の読者は両方を読んだと思います。

最初に注意することは、ハッシュのランダム化はインタープリターの起動時に決定されることです

各文字のハッシュは両方のセットで同じであるため、問題になる可能性があるのは衝突(順序が影響を受ける)がある場合のみです。


その2番目のリンクを差し引くことで、これらのセットのバッキング配列が長さ8で始まることがわかります。

_ _ _ _ _ _ _ _

最初のケースでは、1を挿入します:

_ 1 _ _ _ _ _ _

そして残りを挿入します:

α 1 ? ? ? ? ? ?

次に、サイズ32に再ハッシュされます。

    1 can't collide with α as α is an even hash
  ↓ so 1 is inserted at slot 1 first
? 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

2番目の場合、残りを挿入します。

? β ? ? ? ? ? ?

そして、1を挿入してみてください:

    Try to insert 1 here, but will
  ↓ be rehashed if β exists
? β ? ? ? ? ? ?

そして、それは再ハッシュされます:

    Try to insert 1 here, but will
    be rehashed if β exists and has
  ↓ not rehashed somewhere else
? β ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

したがって、反復順序が異なるかどうかは、βが存在するかどうかだけに依存します。


Βの可能性は、5文字のいずれかが8を法として1にハッシュし、1を法として32をハッシュする確率です。

32を法として1にハッシュするものはすべて8を法として1にハッシュするので、32スロットのうち、5つのうちの1つがスロット1にある可能性を見つけたいと思います。

5 (number of letters) / 32 (number of slots)

5/32は0.15625であるため、2つのセット構成間で順序が異なる確率は15.625%です


まったく奇妙なことではありませんが、これはまさにZero Piraeusが測定したものです。


¹技術的にも、これは明らかではありません。再ハッシュのために5つのハッシュのすべてを一意にふりをすることができますが、線形プローブのため、実際には「束ねられた」構造が発生する可能性が高くなります...実際には影響しません。

128
Veedrac