生日问题

 

理论分析

  • n个人生日各不相同(记作事件A)的概率
    • $P(A)=\frac{C_{365}^n\cdot n!}{365^n}$
  • n个人中存在至少两人生日相同(记作事件B)的概率
    • $P(B)=1-P(A)=1-\frac{C_{365}^n\cdot n!}{365^n}$
  • n-1个人中所有人都与我生日不同(记作事件C)的概率
    • $P(C)=\frac{364^{n-1}}{365^{n-1}}=(\frac{364}{365})^{n-1}$
  • n-1个人中有人与我生日相同(记作事件D)的概率
    • $P(D)=1-P(C)=1-(\frac{364}{365})^{n-1}$

数值模拟

  1. 随着n从2到60变化时,生日相同的理论概率值的变化情况。
import math
import matplotlib.pyplot as plt
    
def birthday_probability(n):
    """
    计算班级里有 n 个人时,至少两人生日相同的概率。
    """
    if n > 365:
        return 1.0  # 超过365人时,必定有人生日相同
    return 1 - math.factorial(365) / (365 ** n * math.factorial(365 - n))

def plot_birthday_probabilities():
    """
    绘制班级人数 n 从 2 到 60 时,至少两人生日相同的理论概率值。
    """
    n_values = range(2, 61)  # n 从 2 到 60
    probabilities = [birthday_probability(n) for n in n_values]

    # 绘图
    plt.figure(figsize=(10, 6))
    plt.plot(n_values, probabilities, marker='o', linestyle='-', color='b', label='Birthday Probability')
    plt.title('Probability of At Least Two People Sharing a Birthday')
    plt.xlabel('Number of People (n)')
    plt.ylabel('Probability')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend()
    plt.show()

# 调用函数绘图
plot_birthday_probabilities()

image-20241215173348666

  1. 做100次数值模拟试验,每一纵列是一次试验结果,蓝点表示30人的生日,如果两个人生日相同,用红点表示。
import numpy as np
import random

def simulate_birthdays(trials=100, people=30):
    """
    进行数值模拟试验,每次试验随机生成若干人的生日。
    蓝点表示30人的生日,红点表示只有两人生日相同的情况。
    """
    results = []
    for _ in range(trials):
        birthdays = [random.randint(1, 365) for _ in range(people)]
        counts = {day: birthdays.count(day) for day in set(birthdays)}
        has_exactly_two = any(count == 2 for count in counts.values())
        results.append((birthdays, has_exactly_two))

    # 绘制模拟结果
    plt.figure(figsize=(12, 8))
    for i, (birthdays, has_exactly_two) in enumerate(results):
        x_values = [i + 1] * people  # 每列的 x 值
        y_values = birthdays       # 每列的生日
        colors = ['red' if has_exactly_two and birthdays.count(day) == 2 else 'blue' for day in birthdays]
        plt.scatter(x_values, y_values, color=colors, alpha=0.4, s=15)

    plt.title('Birthday Simulation: Red Indicates Exactly Two People Sharing a Birthday')
    plt.xlabel('Trial Number')
    plt.ylabel('Day of Year (1-365)')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.show()


# 调用函数绘图
simulate_birthdays()

image-20241215174935126

  1. 数值展示至少有两人生日相同和有人与“我”生日相同的概率对比图。
def same_with_me(n):
    """
    计算班级里有 n 个人时,有人与我生日相同的概率。
    """
    return 1 - (364 / 365) ** (n - 1)

def plot_contrast():
    """
    绘制班级人数 n 从 2 到 60 时,至少两人生日相同的理论概率值。
    """
    n_values = range(2, 61)  # n 从 2 到 60
    probabilities = [birthday_probability(n) for n in n_values]
    same = [same_with_me(n) for n in n_values]

    # 绘图
    plt.figure(figsize=(10, 6))
    plt.plot(n_values, probabilities, marker='o', linestyle='-', color='b', label='two people same birthday')
    plt.plot(n_values, same, marker = 'o', linestyle = '-', color = 'r', label='same with me')
    plt.title('Show the difference')
    plt.xlabel('Number of People (n)')
    plt.ylabel('Probability')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend()
    plt.show()

plot_contrast()

image-20241215175930826

总结

一个班级里两个人生日相同概率较大,而有人与我生日相同概率较小,这很符合我们的日常生活经验。