两个孩子问题
题
一个家庭有两个孩子,每个孩子独立地以 \(\frac12\) 为男孩、以 \(\frac17\) 生在一周的某一天。分别在下面三种已知条件下,求两个都是男孩的概率:
- 至少有一个是男孩。
- 老大是男孩。
- 至少有一个是周二出生的男孩。
一句话
\(1/3\)、\(1/2\)、\(13/27\)——三个答案都对,差别全在条件事件是什么。真正决定答案的是信息怎么到你手里的:同一句"我有个男孩",按不同机制说出口,答案可以是 \(1/3\) 也可以是 \(1/2\)。
关键技巧
按长幼把家庭写成有序对,样本空间 \(\{BB, BG, GB, GG\}\) 等可能。条件概率就是在条件事件里数 \(BB\) 的占比:
- 至少一个男孩:条件事件 \(\{BB, BG, GB\}\),\(BB\) 占 \(\frac13\)。
- 老大是男孩:条件事件 \(\{BB, BG\}\),\(BB\) 占 \(\frac12\)。"老大"把男孩钉在一个具体位置上,另一个孩子就是一枚独立的新硬币。
"至少一个"之所以偏离 \(\frac12\),是因为它没指定是哪个孩子——\(BB\) 家庭有两个男孩可以满足条件,却只被数了一次,而 \(BG\)、\(GB\) 各算一次。
抽样机制才是题面的真身。 "至少一个男孩"对应的机制是:筛选——从所有两孩家庭里挑出有男孩的,再问。若换成"家长随手挑一个孩子,告诉你他的性别",听到"男孩"时:\(BB\) 家庭必然说男孩,\(BG\)/\(GB\) 家庭只有一半概率说男孩,贝叶斯一算
同一句话,两种机制,两个答案。
解
第三问把每个孩子细分成 14 种(性别 × 星期),两个孩子共 \(14^2 = 196\) 种等可能。
- 含"周二男孩"的家庭:老大是周二男孩 14 种,老二是周二男孩 14 种,两个都是重复算了 1 种,共 \(14 + 14 - 1 = 27\) 种。
- 其中两个都是男孩:老大周二男孩、老二任意男孩 7 种,反过来 7 种,重复 1 种,共 \(7 + 7 - 1 = 13\) 种。
为什么一个"周二"能把 \(\frac13\) 拉向 \(\frac12\)?\(BB\) 家庭有两次机会拥有周二男孩,\(BG\) 家庭只有一次——"周二"这个细节几乎把男孩钉在了某个具体孩子身上,重复计数的那 1 种越不显眼,答案越接近第二问。
一般地,若男孩带有一个概率为 \(p\) 的特征(周二 \(p = \frac17\),生日某天 \(p = \frac{1}{365}\)):
\(p = 1\) 回到 \(\frac13\),\(p \to 0\) 趋于 \(\frac12\);\(p = \frac{1}{365}\) 时是 \(\frac{729}{1459} \approx 0.4997\)。
延伸
- 周二版本同样怕机制:若家长随机挑一个孩子,说出他的性别和生日星期,听到"周二出生的男孩",答案回到 \(\frac12\)。\(\frac{13}{27}\) 只在"筛选出至少有一个周二男孩的家庭"这个机制下成立。
- 判断机制的一个问法:如果真相是 \(BG\),对方有没有可能说出"女孩"?有可能(随机挑孩子报性别)——答案 \(\frac12\);不可能(问卷问"你有儿子吗",只统计回答"有"的)——答案 \(\frac13\)。
- 现实里的"独立等概"并不成立:男女出生比约 \(1.05 : 1\),同胞性别也有轻微相关。题目是在理想模型下讲条件概率,别拿它推断真实人口。
- 和三门问题同一个坑:三门问题 里主持人怎么选门决定换门胜率是 \(\frac23\) 还是 \(\frac12\),这里家长怎么选孩子开口决定答案是 \(\frac13\) 还是 \(\frac12\)。条件概率题的第一步永远是写清楚:观察到的事件是被什么过程生成的。
- 常见错误:把"至少一个男孩"当成"某个孩子是男孩",于是答 \(\frac12\);或者用 \(\{BB, BG, GG\}\) 三种无序组合当等可能样本空间——\(BG\) 其实有两种排列,概率是 \(BB\) 的两倍。
数值验证
按 (性别, 星期) 全枚举 196 个有序家庭,分别按"筛选"和"随机挑一个孩子开口"两种机制算:
from fractions import Fraction as F
from itertools import product
kid = [(s, d) for s in "BG" for d in range(7)] # 14 种等可能,d=2 记作周二
fam = list(product(kid, repeat=2)) # 196 个有序家庭(老大, 老二)
P = F(1, len(fam))
both = lambda f: f[0][0] == f[1][0] == "B"
def filtered(cond): # 机制一:筛出满足条件的家庭
return sum(P for f in fam if both(f) and cond(f)) / sum(P for f in fam if cond(f))
print(filtered(lambda f: any(k[0] == "B" for k in f))) # 1/3 至少一个男孩
print(filtered(lambda f: f[0][0] == "B")) # 1/2 老大是男孩
print(filtered(lambda f: ("B", 2) in f)) # 13/27 至少一个周二男孩
def told(pred): # 机制二:随机挑一个孩子如实报告
num = den = F(0)
for f in fam:
for k in f: # 每个孩子被挑中的概率 1/2
if pred(k):
den += P / 2
num += P / 2 * both(f)
return num / den
print(told(lambda k: k[0] == "B"), told(lambda k: k == ("B", 2))) # 1/2 1/2
def trait(p): # 男孩带概率 p 的特征,按类型加权枚举
types = {"B+": p / 2, "B-": (1 - p) / 2, "G": F(1, 2)}
num = den = F(0)
for a, b in product(types, repeat=2):
w = types[a] * types[b]
if "B+" in (a, b):
den += w
num += w * (a[0] == b[0] == "B")
return num / den
for p in (F(1), F(1, 7), F(1, 365)):
print(p, trait(p), trait(p) == (2 - p) / (4 - p)) # 1 1/3 True | 1/7 13/27 True | 1/365 729/1459 True