计算生日悖论概率
假设一个班级有n个人,那么计算这n个人至少有两个人生日相同的概率。
一般情况下,我们感性认识上会觉得班级上至少有两个人生日相同的概率会比较低,毕竟每个人的生日有365种选择,而班级一半只有30人左右,但是实际上计算得到的至少两人生日相同的概率却远远大于我们的感性认识,所以称为生日悖论。
计算生日概率
假设班级有n个人,我们从反面计算至少有两个人生日相同的概率,这个反面就是每个人生日都不同的概率。那么这个概率可以这么计算:
1. 第一个同学的生日有365种选择;
2. 第二的同学的生日有364种选择,这里是因为要保证每个人的生日都不同,所以已经选择过的日期不能再选。
3. 第三个同学的生日有363种选择;
4. 第四个同学的生日有362种选择;
5. 第i个同学的生日有365 - i + 1种选择;
这n位同学的总的选择的数量为:
所以,假设班级上n为同学的生日都不相同的概率为:
然后,包含n位童鞋的一个班级,至少有两个童鞋生日相同的概率为:
替换公式种的生日不同的概率公式prob(n):
来看看至少有两个人生日相同的概率
假设n = 30, (班级有30个人),那么,至少有两个人生日相同的概率为:
p(30) = 0.706316242719
n = 24,
p(24) = 0.507297234324
当班级内人数超过24人后,至少有两人生日相同的概率就已经超过了0.5
代码来啦
代码中,为了防止浮点数连成造成数据溢出,采用了log加法的方式进行计算。
#!/usr/bin/env python
"""
Given a number of people, compute the probability of at least two people have the same birthday
"""
import math
class Solution(object):
def computeProb(self, n):
"""
:type n: int
:rtype: float
Idea: if n > 365, then definitely at least two people will has the same birthday,
when n <= 365, we compute the probability of that these people do not have same birthday,
1th people have 365 choice, 2nd people has 364 choice, 3rd people has 363 choice, etc.
Using log operation to avoid float multipy overflow
"""
assert n > 0, 'n should > 0'
if n > 365:
return 1.0
prob = 0.0
for i in xrange(n):
prob += math.log((365 - i) / 365.0, 2)
return 1.0 - 2.0 ** prob
class BirthdayParadoxImage(object):
def showCurve(self):
x = [i + 1 for i in range(365)]
y = []
prob = 0.0
for n in x:
prob += math.log((365 - n + 1) / 365.0, 2)
current_prob = 1.0 - 2.0 ** prob
y.append(current_prob)
import matplotlib.pyplot as plt
plt.title('probability of at least two people have the same birthday')
plt.plot(x, y, color='blue', lw=2)
plt.show()
if __name__ == '__main__':
so = Solution()
print so.computeProb(20), ', probability of 20 people'
print so.computeProb(23), ', probability of 23 people'
print so.computeProb(40), ', probability of 40 people'
print so.computeProb(364), ', probability of 364 people'
print so.computeProb(365), ', probability of 365 people'
print so.computeProb(400), ', probability of 400 people'
print 'show curve'
image = BirthdayParadoxImage()
image.showCurve()
生日悖论曲线
来看看当班级人数增加时,至少有两个人生日相同的概率是如何变化的: