今日の風景
なぜ人は半額のシールを見ると買ってしまうのか。
お話
あるところに、パーティ好きの二人組がいた。この二人のやるパーティは多種多様だったので、同じ客層はほぼ無かった。ところで、この二人組の最近の悩みは、パーティを主催するのにも飽きて来たことである。そこで、次のパーティを開くにあたって、このような提案をした。
「パーティを開いたときに、客が会場に入ってくるだろ? そこで、会場に入った人数で区切りをつけで、その中に同じ誕生日のペアがいるかどうかを賭けてみるというのはどうだろう?」
当然ながら、同じ誕生日のペアがいる確率は365人になればなるほど近づくだろうし、同じ誕生日でなければ、2人ならば、ほぼ同じ誕生日にならないだろう。それだと、この賭けは面白くない。そこで、できるだけお互いの確率を一緒にしたい。さて、この区切りを何人にすれば、お互いに平等であると言えそうだろうか。
議論
有名な話であり、Wikipediaにも「誕生日のパラドックス」として詳細にまとめられているけれども、解説する。
まず単純な話から始めよう。街中で、二人に声をかけ、その二人の誕生日が違う確率について考えてみよう。二人目が違う誕生日であるということは、改めて確認することなく、一人目の誕生日と一緒ではない、ということだ。
誕生日は365通りあり、そのうちの一つが選ばれる。その一つ以外を選べば違うということになるわけだから、残り364通りとなる。もちろん、誕生日自体は365通りあるわけだから、確率的には364/365 = 約99.72%となる。
さて、今度は3人に声をかけて、誕生日が違う確率について考えてみよう。まず2人が違う確率は364/365だった。そして、3人目は、その中の363通りなので、363/365となる。
ここで、単純に363/365と考えてはだめで、364/365 * 363/365と考えなくてはいけない。なぜなら、363/365だと、365通りのうち、2つの誕生日が含まれている確率だからだ。
しかし、考慮しなければならないのは、この場合、お互いの誕生日ということだ。まず、一人目と二人目を照しあわせ、その次に、一人目二人目と、三人目を照らしあわせないといけない。従って、364/365 * 363/365となる。
先のWikipediaの記事によれば、22人がだいたい五割に近いということになっている。計算の仕方は、1/2 * 2/3が2/6 = 1/3になるように、分母を乗算したものに対して、分子を364 * 363 * 362 ...といったようにしていけばよい。Haskellで書くなら次のようになるだろう:
import Text.Printf birth_probability :: Integer -> IO () birth_probability 0 = return () birth_probability n = do putStrLn $ printf "Member :: %i" $ n + 1 putStrLn $ show $ fromIntegral (product [(365 - n)..364]) / (365 ^ n) birth_probability $ n - 1 main :: IO () main = birth_probability 50
ここで顕著な例として、10人、20人、22人、23人、30人、40人の場合を取りだしてみると、次のような確率となる。
Member :: 10 0.8830518222889224 Member :: 20 0.58856161641942 Member :: 22 0.5243046923374499 Member :: 23 0.49270276567601456 Member :: 30 0.2936837572807314 Member :: 40 0.10876819018205101
この計算を信用するならば、10人なら約9割の確率で外れ、20人なら約6割、最も公平なのは23人の場合で5割、30人なら3割で40人なら1割しか外れない。
これが「誕生日のパラドックス」と呼ばれるのは、このように、直感的には少ないと思われる人数であっても、誕生日のペアが成立することにあるのだが、ここはプログラマ、さっそくこれを検証してみることにするわけだけど、コード自体は非常に簡単だ。
[10, 20, 22, 23, 30, 40].each do |n| not_uniq_birthday = 0 1.upto(1000000) do people = Array.new(n) { Random.rand(366)} not_uniq_birthday += 1 if people.size == people.uniq.size end puts "#{n}人の場合 => #{not_uniq_birthday}回外れ" end
実行すると、以下のようなログとなる。
10人の場合 => 883407回外れ 20人の場合 => 589574回外れ 22人の場合 => 525452回外れ 23人の場合 => 493833回外れ 30人の場合 => 294524回外れ 40人の場合 => 109550回外れ
びっくりするほど、計算通りに外れてくれることがわかる。
結論
誕生日のパラドックス自体は有名な話ではあるけれども、しかし実際にそういう風に計算ができる、というのは知っていたとしても、では試行すると、本当にその計算に近い数字が出るのか、ということをやってみた人は少ない気がする。プログラミングによって、こういう素朴なことを試せるようになったようになったことはいいことだと思う。計算だけでなく、実験もどんどんやっていって、「確かに計算通りになるんだな!」というのを実感していってみたいと思う。
- 作者: マーティンコーエン,Martin Cohen,矢橋明郎
- 出版社/メーカー: 筑摩書房
- 発売日: 2008/10/08
- メディア: 文庫
- 購入: 5人 クリック: 4回
- この商品を含むブログ (11件) を見る