概要
誕生日のパラドックスとは、「同じ誕生日の人がいる確率が50%を超えるのは、何人集まれば良いか?」という問題において、結果が直感と反しているというパラドックスです。
確率を計算すると以下の結果になります。
- 40人の場合は、
約89.12%
- 23人の場合は、
約50.73%
個人的にも納得できないので、Pythonを使って検証をしていきたいと思います。
計算式
同じクラス内に1組以上の誕生日が一致する確率は以下の式から導き出せます。(nは1クラスの人数)
p(n) = 1 - \frac{365!}{365^n(365-n)!}
コーディング
関数①:計算式を基にコーディング
まずは、計算式を基にプログラムを書いてみました。
def birthday_paradox_prob_calc(n: int) -> float:
'''
誕生日のパラドックスの計算を行う
Args:
n (int): 人数
Returns:
float: 確率(%)
'''
if n > 365:
return 100.0
prob_no_shared_birthday = 1.0
for i in range(n):
prob_no_shared_birthday *= (365 - i) / 365
prob_shared_birthday = 1 - prob_no_shared_birthday
return prob_shared_birthday * 100
0から100までの折れ線グラフを作成すると、以下のようなグラフができます。
たしかに、23人くらいで50%くらいになっています。
関数②:シミュレーションを行うようにコーディング
こちらの関数は、実際に1から365の配列を作成し配列内に重複があるかどうかの割合を返すプログラムです。try_count
に大きい数値を指定することで、より正確なシミュレーションができます。
import random
def birthday_paradox_prob_act(n: int, try_count: int = 10000) -> float:
'''
誕生日のパラドックスのシミュレーションを実行する
Args:
n (int): 人数
try_count (int): 試行回数
Returns:
float: 確率(%)
'''
if n > 365:
return 100.0
true_count = 0
for _ in range(try_count):
random_numbers = [random.randint(1, 365) for _ in range(n)]
if len(random_numbers) != len(set(random_numbers)):
true_count += 1
return (true_count / try_count) * 100
試行回数を50を指定するとグラフは以下のようになりました。
(50を指定すると各人数のところで50回試行しその割合をグラフに表示します。そのため上がったり下がったりしています。)
試行回数を10,000を指定するとグラフは以下のようになり、ほぼ関数①と同じ形になりました。
グラフを出力
matplotlibを使用して、2つのグラフを表示します。
import matplotlib.pyplot as plt
def main():
x = list(range(0, 101, 5))
calc_data = [birthday_paradox_prob_calc(n) for n in x]
act_data = [birthday_paradox_prob_act(n) for n in x]
plt.rcParams['font.family'] = 'MS Gothic'
plt.plot(x, calc_data, marker='o')
plt.plot(x, act_data, marker='x')
plt.title('誕生日のパラドックス')
plt.xlabel('人数')
plt.ylabel('確率 (%)')
plt.grid(True)
plt.show()
試行回数を50を指定するとグラフは以下のようになりました。
ぶれてはいますが、関数①のグラフと大体同じになってますね。
(青色が関数①、オレンジ色が関数②)
試行回数を10,000を指定するとグラフは以下のようになり、よくみると僅かにずれていますが、確率が収束したのが分かります。
おわりに
誕生日のパラドックスを検証するプログラムを作ってみました。
冒頭で話した、23人で50%というのは正しそうです...
ちょっと悔しいですが、気になった問題があったら検証してみたいと思います。
ここまで読んでいただきありがとうございました。