ランダムな整数の衝突#
UUID バージョン 4 [1] のようにランダムで十分長い整数は、 同じ整数が選択される(以降、「衝突する」)確率が十分低いため、 単一のプロセスでなく複数のプロセスやコンピュータ上で生成される ID などで 使用されることがある。 ここでは、そのような乱数が衝突する確率が実際どの程度になるのか計算してみる。
衝突する確率#
まず、衝突する確率の計算式を考える。 整数を \(0\) から \(m-1\) までの \(m\) 個の中から \(n\) 回選択する場合、 衝突しない確率は、
\[
p(m, n) = 1 -
\frac{m }{m} \cdot
\frac{m-1 }{m} \cdot
\frac{m-2 }{m} \cdot
\frac{m-3 }{m} \cdot \cdots \cdot
\frac{m-n+1}{m}
\]
のように書ける。
選択する整数の数が少ない場合#
選択する整数の数 \(n\) が少ない場合はコンピュータで比較的容易に計算できる。 ただし、そのままの計算式では \(m\) が大きい場合に 浮動小数点数の打ち切り誤差で正しく計算できなくなるため、 計算式を変形しておく。
\[\begin{align*}
p(m, n) &= 1 -
\frac{m }{m} \cdot
\frac{m-1 }{m} \cdot
\frac{m-2 }{m} \cdot
\frac{m-3 }{m} \cdot \cdots \cdot
\frac{m-n+1}{m}
\\
&= 1 - \prod_{i=0}^{n-1} \frac{m - i}{m}
\\
&= 1 - \prod_{i=0}^{n-1} \left(1 - \frac{i}{m} \right)
\\
&= 1 - \exp\left(\sum_{i=0}^{n-1} \log\left(1 - \frac{i}{m} \right) \right)
\end{align*}\]
これをもとにして確率の計算をすると以下のようになる。
Hint
122 ビットは UUID バージョン 4 の場合にあたる。
近似式#
選択する整数の数 \(n\) が小さくない場合も考える。 \(m \gg n \gg 1\) とし、 マクローリン展開
\[
\log(1 - x) = - \sum_{k=1}^\infty \frac{x^k}{k} \approx -x
\]
を用いると、
\[\begin{align*}
\sum_{i=0}^{n-1} \log\left(1 - \frac{i}{m} \right) & \approx
- \sum_{i=0}^{n-1} \frac{i}{m}
\\
& = - \frac{n(n-1)}{2m}
\\
& \approx - \frac{n^2}{2m}
\end{align*}\]
となるから、
\[
p(m, n) \approx 1 - \exp\left(- \frac{n^2}{2m} \right)
\]
のように近似できる。
これをもとに、\(m \gg n \gg 1\) が 1000 倍以上の差で成り立つような場合の確率の計算を行うと、以下のようになる。
これを近似しない場合と組み合わせると、以下のようになる。
まとめ#
ランダムな整数が衝突する確率を計算してグラフにすることができた。 ランダムな整数で ID などを決定する際に参考にしたい。