修改Python生日悖论代码 求解4人生日间隔≤7天概率50%的人数n
方案说明
你现有的代码是用来计算「至少两人生日相同」的概率,核心判断逻辑和你需要的「至少4人生日间隔不超过7天」完全不匹配,需要替换核心判断部分,具体实现思路和修改后的代码如下:
核心判断逻辑实现步骤
- 先对单次模拟生成的生日数组做升序排序
- 处理生日的环形特性:将排序后的数组每个元素加365,拼接到原数组末尾,避免12月底和1月初的跨年间隔计算错误
- 用滑动窗口遍历排序后的数组:如果存在任意窗口
[i, i+3]满足末尾减首元素≤7,说明该窗口内4人生日间隔都在7天以内,本次模拟计数为成功
修改后的完整代码
import numpy import matplotlib.pylab as plt no_of_simulations = 10000 # 适当提高模拟次数,降低随机误差 milestone_probabilities = [50, 75, 90, 99] milestone_current = 0 def birthday_paradox(no_of_people, simulations): global milestone_probabilities, milestone_current # 人数不足4的时候直接返回0概率 if no_of_people <4: return 0.0 match_count = 0 # 假设一年365天 for sim in range(simulations): birthdays = numpy.random.choice(365, no_of_people, replace=True) birthdays_sorted = numpy.sort(birthdays) # 处理环形跨年问题 birthdays_extended = numpy.concatenate([birthdays_sorted, birthdays_sorted + 365]) found = False # 滑动窗口判断4人间隔 for i in range(len(birthdays_extended)-3): if birthdays_extended[i+3] - birthdays_extended[i] <=7: found = True break if found: match_count +=1 success_fraction = match_count / simulations if milestone_current < len(milestone_probabilities) and success_fraction*100 > milestone_probabilities[milestone_current]: print(f"P(至少4人生日间隔不超过7天 | 人数={no_of_people}) = {success_fraction:.4f}") milestone_current += 1 return success_fraction def main(): people_nums = [] success_rates = [] # 不需要遍历到365,概率到99%就可以停止 for i in range(1, 100): people_nums.append(i) rate = birthday_paradox(i, no_of_simulations) success_rates.append(rate) if milestone_current >= len(milestone_probabilities): break plt.plot(people_nums, success_rates) plt.xlabel("人数") plt.ylabel("概率") plt.title("至少4人生日间隔不超过7天的概率") plt.grid(True) plt.show() main()
额外优化建议
- 如果对精度要求更高,可以把
no_of_simulations调整到20000以上,不过运行时间会对应变长 - 滑动窗口的判断可以用numpy的向量化操作代替循环,进一步提高运行速度:
numpy.any(birthdays_extended[3:] - birthdays_extended[:-3] <=7)
内容的提问来源于stack exchange,提问作者Stunts1897
相关产品推荐
相关产品推荐

