誕生日問題(直感に反する確率のパラドックス)
「わずか23人で50%以上が同じ誕生日?」人間の直感がバグる組み合わせ爆発の謎
- 1
- 誕生日問題(直感に反する確率のパラドックス)の本質的な定義と直感的ビジュアルをシミュレーターで体験できる。
- 2
- 公式や証明の背景にある数学的意味と、厳密な導出ステップを解説。
- 3
- 実社会における工学応用(ハッシュ関数の衝突確率評価(誕生日攻撃シミュレータ))のTypeScript実装コードを収録。
なぜこれを学ぶのか? — 現実社会とテクノロジーでの価値
なぜ生まれたのか?
「わずか23人で誕生日が一致する確率が50%を超える」という直感の裏切りを通じて、組み合わせ爆発(nC2)の凄まじさを理解するために生まれた。
身につく武器・思考力
「自分と誰か」ではなく「あらゆるペアの比較」という多対多の思考法が身につき、暗号技術やサイバーセキュリティの根本脆弱性を直感できる。
実社会・ITでの活躍現場
- •暗号理論における「誕生日攻撃(Birthday Attack)」とハッシュ衝突耐性検証
- •ブロックチェーン(ビットコイン等)の暗号学的安全性の根拠(SHA-256)
- •大規模データベースにおけるUUID・プライマリキーの衝突リスク試算
- •会議や懇親会の自己紹介アイスブレイク(実際に一致して盛り上がる実用ネタ)
Layer 1 — 直感・シミュレーター
部屋に集まった人数(人)をスライダーで 2人 〜 60人 まで動かしてみよう。「自分と同じ誕生日の人がいる確率」ではなく「誰か2人の誕生日が一致するペアがある確率」に注目すると、たった23人で確率が 50.7% を超える驚きを実感できます。さらに「ランダムクラス生成実験」ボタンで、実際に同じ誕生日のペアが見つかるかを何度でも試せます。
23人のランダムクラスを生成してみる
実際にランダムに誕生日を割り振ったとき、同じ誕生日の人が見つかるか検証します。
Layer 2 — 定義・受験・証明
定義
誕生日問題(Birthday Problem / Birthday Paradox)とは、「何人集まれば、その中に誕生日が同じであるペアが少なくとも1組存在する確率が 50% を超えるか?」という問題である。 1年を365日とし、各日に生まれる確率が等しいと仮定した場合、わずか 人でその確率は約 50.7% に達する。 これは「自分と同じ誕生日の人を探す確率(約 )」ではなく、「部屋の中のあらゆる2人の組み合わせ総数 通りのペア」が存在するためである。
公式・数理モデル
証明・導出
余事象(全員の誕生日が完全にバラバラである確率)による計算: 人の誕生日が全員異なる事象を考える。 - 1人目の誕生日は何日でもよい(確率 )。 - 2人目の誕生日は、1人目と異なる日(364日の中のいずれか)でなければならない(確率 )。 - 3人目の誕生日は、先頭2人と異なる日(363日の中のいずれか)でなければならない(確率 )。 - 同様に 人目は となる。
全員が異なる誕生日である確率 は:
よって、少なくとも1組が同じ誕生日である確率 は余事象より:
のとき:
人のクラスでは約 89.1%、 人の講義室では 99.9% の確率で誰かが同じ誕生日になる。
押さえておきたいポイント
- 「自分と誰か」を比べると1人の対比(22通り)だが、グループ全体では 通りものペアが存在する
- ペアの数が 253 組もあるため、1回の比較でハズレる確率が でも全体では一気に確率が跳ね上がる
- 暗号理論・サイバーセキュリティにおける「誕生日攻撃(Birthday Attack)」の基礎理論
- ハッシュ関数の出力ビット長が ビットのとき、わずか 回の試行でハッシュ衝突が発生する(SHA-256などの必要性の根拠)
本トピックの内容・数理モデルは、文部科学省学習指導要領(算数・数学・情報)および国際標準カリキュラムに準拠し、エンジニアリング現場の実装事例と照らし合わせてMath World Lab編集部により検証・作成されています。
Layer 3 — 工学応用・現場実装
ハッシュ関数の衝突確率評価(誕生日攻撃シミュレータ)
ブロックチェーンや暗号署名において、データハッシュの一致(コリジョン)脆弱性を評価するための数学的計算スクリプト。
1// 誕生日衝突確率の高速計算2export function calculateBirthdayCollisionProbability(peopleCount: number, daysInYear: number = 365): number {3 if (peopleCount > daysInYear) return 1.0;4 if (peopleCount <= 1) return 0.0;56 let probAllDifferent = 1.0;7 for (let i = 0; i < peopleCount; i++) {8 probAllDifferent *= (daysInYear - i) / daysInYear;9 }1011 return 1.0 - probAllDifferent;12}1314// 実際のランダム試行によるクラス生日検証15export function generateRandomClassTrial(n: number): { hasDuplicate: boolean; matchedBirthdays: number[] } {16 const birthdays: number[] = [];17 const countMap = new Map<number, number>();18 const duplicates: number[] = [];1920 for (let i = 0; i < n; i++) {21 const day = Math.floor(Math.random() * 365) + 1; // 1〜365日目22 birthdays.push(day);23 countMap.set(day, (countMap.get(day) || 0) + 1);24 }2526 countMap.forEach((count, day) => {27 if (count > 1) duplicates.push(day);28 });2930 return {31 hasDuplicate: duplicates.length > 0,32 matchedBirthdays: duplicates,33 };34}
次に学ぶならコレ!おすすめトピック
この単元と深い繋がりを持つ、あわせて学ぶと理解が深まるおすすめ単元