前三局都是狼,这局我肯定是好人?一个被你天天误用的概率直觉,正在统治整个计算机世界

3 阅读8分钟

一个狼人杀餐桌上的经典翻车现场

打开局面之前,先讲一个你大概率亲历过、或者亲手翻过车的场景。

狼人杀连续三局,你都被发到了狼人牌。第四局开始前你抓起牌,还没看,就拍着胸口对桌上的人说:

“放心吧,前三局我都是狼了,这局从概率上讲肯定不是。”

听起来很有道理,对吧?四局连续当狼好像确实挺夸张的。

但这句话错得非常彻底,错到它有一个专门的名字:赌徒谬误(Gambler's Fallacy)。更要命的是,这个看上去只在牌桌上犯的小错,恰好踩中了整个计算机世界一根最深、最隐蔽的神经。

我们一层一层来拆。

第一层:你以为概率会“自我平衡”,但牌没有记忆

先把最朴素的反驳摆出来:每一局狼人杀的身份分配,是独立事件

只要洗牌足够充分、座位是随机的,这一局你抽到狼人的概率,和你前三局抽到了什么完全没关系。卡牌不会觉得“这位老哥连当三把狼,怪不好意思的,这局让让他”,发牌的法官也不会有这种心理负担。

简单算一下。假设是 10 人局、4 狼配置,那你每一局当狼的边际概率就是:

410=40%\frac{4}{10}=40\%

如果你站在第一局开始之前,预测“接下来连续四局都是狼”,那概率确实很低:

0.442.56%0.4^4 \approx 2.56\%

但当前三局已经实实在在发生了,它们的条件概率就变成了 1。剩下要计算的只是单独这一局——依然是稳稳的 40%。

之所以“连续四局都是狼”听起来很离谱,是因为你站在起点向前看四局;当三局已经实现,你已经穿过了那条窄路,第四局只是普通的一局而已。

赌徒谬误的本质,就是把独立事件想象成有“补偿机制”的相依事件。轮盘连续开了五次红,就觉得下一把“该出黑了”——轮盘没有记忆,它只有自己的机械结构和概率分布。

更有意思的是它的对称谬误:热手谬误(Hot Hand Fallacy)。如果你的直觉是“连续出红,下一次更可能是红”,那在独立随机事件里也错了。两个完全相反的直觉同样翻车,这本身就足以说明:人类对随机性的直觉极其不可靠

插一段:我是不是已经站在 2.56% 的时间线里了?那该买彩票吗?

这里有个很有意思的追问:

如果我前三把都是狼,那是不是说明,在这一天、这个时间点、我所身处的时间线,已经是那个小概率分支了?

答案是:对,但别急着买彩票。

准确地说,如果每局当狼概率是 40%,那么“前三局都是狼”的概率是:

0.43=6.4%0.4^3 = 6.4\%

“连续四局都是狼”的概率才是:

0.44=2.56%0.4^4 = 2.56\%

所以,如果你已经连续三局都是狼,你确实可以说:从第一局开始往前看,你刚刚穿过了一条 6.4% 的小概率路径。

但重点是:你已经站在这个分支里了。

它说明的是:

“刚才发生的事情挺罕见。”

它不说明:

“接下来我更容易遇到另一个小概率好事。”

彩票机器不会因为你刚刚在狼人杀里经历了小概率事件,就突然给你加一个“命运补偿 buff”。随机世界不是剧情片,不负责前后呼应。

真正危险的直觉是:

“既然我今天已经进入了小概率时间线,那今天是不是整体运势异常?”

这其实是人脑在给随机性编故事。

更准确的说法是:

你不是进入了一条“幸运/倒霉时间线”;你只是事后发现,自己处在某个低概率事件已经发生的样本路径上。

现实里我们每天都会经历大量随机事件:刷到某首刚想到的歌、连续看到同一个数字、朋友刚好提到你昨天想的东西、某个冷门词突然一天内出现三次。因为一天里发生的随机事件太多了,总会有一些事情在事后显得很玄学

所以,该不该买彩票?

娱乐可以买一张。

但如果你指望“前三把都是狼”给彩票加 buff,那就又回到了赌徒谬误。

更概率论地说:

前三把都是狼,只更新了你对“狼人杀发牌机制是否公平”的怀疑;它没有更新你对“彩票开奖机制”的任何信息。

第二层:大数定律不是用来“补偿”的,是用来“稀释”的

这里要插一刀,因为很多人会用“大数定律”来给赌徒谬误背书:你看,长期来看红黑各占一半,所以最近红多了,黑就该追上来了——这不正是大数定律吗?

不是。

大数定律的真正陈述是:当试验次数 nn \to \infty样本均值依概率收敛到期望值

但它的生效机制,不是通过短期补偿实现的。不是“前面欠的,后面要还”。

它靠的是稀释

前期偏差并不会被未来反向纠正,而是被越来越多次的独立试验慢慢淹没,使得长期频率趋近于真实概率。

换句话说,前三局都是狼这个观测,在 nn \to \infty 的尺度上,权重会越来越小。它不会被“还回来”,它会被“忘掉”。

第三层:贝叶斯反转——也许你真的应该相信下一局还是狼

到这里,“独立性”似乎完美解释了一切。但还有一个反直觉的转折,必须讲出来才完整。

前面所有分析都隐含了一个前提:这游戏是公平的

这是一个被默认接受的先验。

但如果你对公平性本身就有不确定性——比如你怀疑这位法官洗牌不均匀、座位编号有规律、发牌顺序不够随机——那么连续三局都是狼这个观测,就不再只是“运气不好”。它也可能是在提醒你:这个系统本身可能有偏。

如果我们把“你这个座位真实的当狼概率”看成一个未知参数 θ\theta,那么贝叶斯式的写法大概是:

P(第四局是狼前三局都是狼)=P(θ)P(θ数据)dθP(\text{第四局是狼} \mid \text{前三局都是狼}) = \int P(\text{狼} \mid \theta) \cdot P(\theta \mid \text{数据}) \, d\theta

其中 θ\theta 是“你这个座位真实的当狼概率”。前三局连续是狼这个观测,会把后验分布 P(θ数据)P(\theta \mid \text{数据}) 往更大的 θ\theta 值推一点。

所以,在常见的贝叶斯模型下,理性推理反而会告诉你:下一局当狼的概率不仅不应该下调,反而可能应该上调

这就形成了一个非常漂亮的三层结构:

  • 朴素直觉说:“概率会自我平衡。”——
  • 严格独立性说:“概率不变。”——在公平假设下
  • 贝叶斯说:“如果公平假设本身待检验,那么连续异常也是信息。”——这更接近真实世界。

记住这个三层结构,因为接下来你会看到,整个计算机科学就是在这三层之间反复横跳。

切到计算机:一个看似无害的直觉,如何统治了你每天用的所有软件

狼人杀的故事讲完了,但概率论在计算机里的戏份才刚刚开场。

第一站:你的电脑里其实没有“随机”

你写代码时随手敲下的 random.random(),严格来说是个确定性算法。给定相同的种子,输出的序列完全一致。

import random

random.seed(42)
print([random.random() for _ in range(3)])
# 永远是 [0.6394..., 0.0250..., 0.2750...]

这种东西的学名叫伪随机数生成器(PRNG, Pseudo-Random Number Generator)。

这就引出一个非常有趣的问题:如果你用 PRNG 模拟狼人杀发牌,那“独立性”其实是工程上制造出来的幻觉——每一次抽取实际上都由内部状态完全决定。

但只要 PRNG 设计得足够好,并通过大量统计测试,它在模拟、抽样、游戏、随机化算法等场景中就足够像随机。

注意,是“足够像”,不是“真的随机”。

这一区别在密码学场景里会变得致命。普通 PRNG 的输出如果能被攻击者反推出种子或内部状态,后续所有“随机数”都可能被预测。密码学场景必须使用 CSPRNG(Cryptographically Secure Pseudo-Random Number Generator),或者从操作系统提供的安全随机接口取数。

这里和狼人杀形成了一个镜像关系:

  • 在狼人杀里,你如果无端怀疑独立性,可能是过度多疑。
  • 在密码学里,你如果天真相信“看起来随机就够了”,可能就是安全事故。

同样一个独立性概念,在不同场景下要被反向使用——这正是工程师的素养所在。

第二站:生日悖论统治哈希和 ID 系统

再说一个看似冷知识、但在计算机里到处都是的现象:生日悖论

23 个人里,至少有两人同生日的概率,超过 50%。第一次听到的人都觉得不可能,因为 23 远小于 365,凭什么?

关键在于:你算的不是“某一个特定的人和别人撞日”,而是“任意两人撞日”。

23 个人有:

(232)=253\binom{23}{2}=253

对组合,概率被这个组合数狠狠放大。

这个看起来像聚会冷知识的东西,直接影响了哈希、随机 ID 和密码学安全边界。

nn 个 key 随机映射到 mm 个可能位置里,发生至少一对冲突的概率近似为:

1en(n1)/(2m)1-e^{-n(n-1)/(2m)}

nn 达到 m\sqrt{m} 量级时,“至少有一对撞上”就已经不稀奇了。

这里有一个容易讲错的地方:哈希表的负载因子常常控制在 0.7 左右触发扩容,但这并不是为了让“至少一次冲突”的概率保持很低。事实上,当元素数量达到桶数量的常数比例时,至少一次冲突几乎必然发生。

哈希表真正控制的是:平均链长、探测序列长度、缓存局部性和性能退化。它不是在追求“没有冲突”,而是在追求“冲突可控”。

生日悖论更直接影响的是大空间哈希和随机 ID。

比如 Git 传统上使用 SHA-1。SHA-1 输出是 160 位,如果把它理想化成均匀随机函数,那么生日攻击的量级是 2802^{80},也就是输出空间平方根的量级。现实里,SHA-1 已经不再被认为是强抗碰撞的安全哈希,所以 Git 社区也设计了向 SHA-256 迁移的方案。

UUID v4 也是类似逻辑。它总长 128 位,其中一部分位用于版本和变体标记,实际随机性通常是 122 位。122 位随机空间足够大,所以在正常工程规模下,随机撞 ID 的概率小到可以忽略。

这里藏着的概率论思想,和狼人杀那个错误其实是同一类:搞错了你在算什么事件

赌徒谬误把“一开始预测四连狼”和“已发生三局后预测第四局”混为一谈;生日悖论的反直觉,则是把“我和某个特定人撞日”和“任意两人撞日”混为一谈。

事件边界划在哪里,决定了概率差好几个数量级。

第三站:布隆过滤器——主动接受错误率,换内存

如果你有 10 亿个 URL,要快速判断“这个 URL 我之前见过吗”,精确做法是哈希集合,但内存会爆炸。

布隆过滤器(Bloom Filter)给出的是一个概率妥协方案:用 kk 个哈希函数,把每个元素映射到位图的 kk 个位置,全部置 1;查询时检查这 kk 个位置是否都为 1。

它的奇特性质是非对称的

  • 永远不会假阴性:说“没见过”,就一定没见过。
  • 但会有小概率假阳性:说“见过”,其实可能没见过。

假阳率近似为:

(1ekn/m)k(1-e^{-kn/m})^k

其中 mm 是位图大小,nn 是插入元素数,kk 是哈希函数个数。通过调参,可以把假阳率压到 1%、0.1%,甚至更低。

这不是 bug,而是设计目标。

布隆过滤器的本质,是工程里非常经典的一句话:用可控错误率换资源效率

历史上,Bitcoin 的 BIP37 就用 Bloom Filter 支持轻量客户端做交易过滤:轻节点不用下载所有交易,只需要告诉全节点一个过滤器,让全节点返回可能相关的数据。当然,这个方案后来也暴露出隐私和 DoS 等问题,Bitcoin Core 从 0.19 起默认不再提供这类 Bloom filter 服务。

这恰好说明概率结构在工程里不是抽象玩具。它会被设计进系统,也会因为现实攻击模型而被重新评估。

在狼人杀里,我们是被概率直觉误导;到了布隆过滤器这里,工程师反过来把概率误差装进系统核心,然后精确地控制它。

第四站:随机化算法——把不确定性当武器

确定性算法在某些问题上代价极高,但允许“小概率慢”或者“小概率出错”,就能极大简化问题。

两类典型代表:

Las Vegas 算法:结果一定对,但运行时间随机。

随机化快速排序就是经典例子。随机选 pivot,期望复杂度是:

O(nlogn)O(n\log n)

最坏情况仍然是:

O(n2)O(n^2)

但如果 pivot 是随机选的,对手就很难提前构造一个固定输入,让你每次都选到最差划分。

这里有一个非常深刻的思想:随机化让“对抗输入”这个概念变得更难成立

攻击者可以知道你的算法,但如果不知道你的随机选择,就很难稳定把你打进最坏情况。

Monte Carlo 算法:运行时间通常可控,但结果允许小概率出错。

Miller–Rabin 素数测试就是典型。对很多版本的表述来说,每轮测试对合数的误判概率上界可以压到 1/41/4,独立跑 kk 轮后,错误率上界是:

4k4^{-k}

跑几十轮以后,这个错误概率已经低到工程上可以接受。

许多密码系统,尤其是 RSA 密钥生成,会依赖高置信度的素数判定。这里的思想不是“我们随便赌一把”,而是“我们把错误概率压到远低于系统中其他风险的量级”。

这和日常直觉完全相反。

人类讨厌“不确定”,工程系统却经常主动引入不确定性,因为它能换来速度、鲁棒性和抗对抗性。

第五站:贝叶斯推断——现代 AI 的一种底层语言

回到狼人杀那个三层结构里的最后一层:贝叶斯。

它不是一个抽象的哲学问题,而是机器学习里处理不确定性的重要语言之一。

最经典的例子是朴素贝叶斯垃圾邮件过滤器。它估计的是:

P(spam词1, 词2, ...)P(\text{spam} \mid \text{词1, 词2, ...})

直觉上,就是看到“中奖”“发票”“免费”“点击链接”这些词以后,更新一封邮件是垃圾邮件的概率。每来一封新邮件、每收到一次“标记为垃圾”的反馈,模型都可以继续调整自己的判断。

现代 LLM 也可以从条件概率的角度理解:给定上文,模型输出的是下一个 token 的概率分布:

P(下一个 token已有 tokens)P(\text{下一个 token} \mid \text{已有 tokens})

Temperature、top-k、top-p 采样,都是在这个分布上做不同形式的抽样和截断:

  • 温度越低,输出越接近确定性贪心。
  • 温度越高,模型越愿意探索低概率选项。
  • top-k 限制候选 token 数量。
  • top-p 则保留累计概率达到某个阈值的一组候选。

你日常和 AI 对话,本质上就是在和一个巨大的条件概率模型互动。它给你的每一个字,都不是从虚空里“想出来”的,而是在你的上下文条件下,从某个概率分布里生成出来的。

再比如多臂老虎机(Multi-Armed Bandit)问题:系统要在“探索新选项”和“利用已知最优选项”之间做权衡。Thompson Sampling 这类贝叶斯方法,会给每个选项维护一个不确定性分布,然后一边试探,一边更新。

推荐系统、广告投放、实验平台、策略优化里,到处都有这种思想的影子。

也就是说,狼人杀里那个“我该不该怀疑发牌机制”的问题,换一个名字,就变成了机器学习里的核心问题:

我现在看到的数据,到底是在反映随机波动,还是在揭示系统结构?

一个收束的观察:两个看似矛盾的洞察

把这些线索串起来看,会发现概率论在计算机里扮演着一个反直觉但极其有用的角色:

  • 我们用确定性硬件模拟随机性:PRNG。
  • 我们用随机性驯服确定性的最坏情况:随机化算法。
  • 我们用概率换取资源效率:布隆过滤器。
  • 我们用贝叶斯更新逼近真实世界的不确定性:机器学习与推荐系统。

这些应用反复演绎着两个看似矛盾的洞察:

什么时候该相信独立性假设?

什么时候该怀疑它?

回到那个狼人杀餐桌:

前三局都是狼,对下一局牌局本身没有信息——如果每局真的独立、公平随机。

但前三局都是狼,对法官是否真的在公平洗牌可能有信息——如果公平性本身值得怀疑。

买彩票也是同理:

你刚刚经历了狼人杀里的小概率事件,并不会改变彩票机的随机机制。它只说明你刚才穿过了一条少见的样本路径,不说明宇宙接下来会给你安排补偿剧情。

工程上犯的很多错误,根子上都是把这两个问题搞混了:

  • 以为 PRNG 真的独立,于是密码学翻车。
  • 以为哈希函数真的均匀,于是被恶意构造的 collision attack 打挂。
  • 以为 A/B 测试两组真的同分布,于是混杂变量没控制,得出错误结论。
  • 以为一个小概率事件刚发生,另一个无关小概率事件就更可能发生,于是转头去买彩票。

赌徒谬误不是一个发生在牌桌上的小笑话。

它是人类直觉和数学世界之间一道永远的裂缝

而整个计算机科学,很大程度上就是在这道裂缝上小心翼翼地搭桥。


下次再遇到“前三局都是狼,所以这局肯定不是”的说法,不妨把它翻译成一个更准确的问题:

我们到底是在讨论下一局的随机结果,还是在讨论发牌机制本身是否可信?

如果发牌机制公平,前三局不会改变第四局的概率。
如果发牌机制可疑,前三局反而可能成为怀疑机制的证据。

概率论真正教我们的,不是给每个巧合找一个玄学解释,而是在看到巧合时,多问一句:

这个结果,是随机波动,还是机制偏差?