理论分析
- 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}$
数值模拟
- 随着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()
- 做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()
- 数值展示至少有两人生日相同和有人与“我”生日相同的概率对比图。
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()
总结
一个班级里两个人生日相同概率较大,而有人与我生日相同概率较小,这很符合我们的日常生活经验。