Skip to content

苏格拉底:寻找最大的麦穗的故事

本文介绍了博弈论中经典的 37% 法则及其数学推导过程。

最大的麦穗

相传苏格拉底曾带领他的学生们在一片麦田里散步。学生们问他:怎样才能找到最合适的终身伴侣?

苏格拉底望着麦田,给他们布置了一项任务:「走进麦田,找到最大的麦穗,但你们一路上只能往前走,不能回头。」

学生们一边走一边挑选,田里到处都是大麦穗。但哪一株才是最大的呢?他们低着头走着,一株一株地查看。看这一株摇摇头,看那一株也摇摇头。他们总以为最大的麦穗还在前面。虽然也摘了几株,但都不满意,便扔掉了。他们觉得机会还多得很,不必过早作决定。

学生们继续低着头走了很久,一路上仔细挑选。忽然,他们听到苏格拉底深沉浑厚的声音:「你们已经走到尽头了。」此刻,两手空空的学生们才明白发生了什么,心中十分沮丧。

苏格拉底对他们说:「这片麦田里肯定有最大的麦穗,但你们未必能遇到它;即使遇到了,也未必能作出正确的判断。因此,最大的麦穗就是你们刚刚摘下的那一株。」

这个故事告诉我们:人生就像在麦田里行走,同样是在寻找最大的麦穗。有些人看到一株饱满成熟的麦穗,便毫不犹豫地抓住机会摘下;有些人则不停地东张西望,一次又一次地错失良机。当然,目标应当是最大的麦穗,但握在手中的那一株才是最实在的现实。

那么问题来了:有没有一种方法,能帮助我们尽可能高效地找到最大的麦穗呢?

宝箱游戏

我们再来看另一个例子。假设有一种赌博游戏,规则如下:共有 mm 个宝箱,每个宝箱中随机装有 00xx 美元之间的奖金,且服从均匀分布。但是,你不知道宝箱中奖金的最大值 xx 是多少。一旦你打开一个宝箱看到奖金,你有两个选择:要么拿走奖金并停止游戏,要么丢弃这个宝箱再打开另一个。不过,被丢弃的宝箱不能再被选择。

现在问题来了:你应该如何制定策略,才能获得尽可能多的钱?自然是钱越多越好。

如果我们不使用任何策略,随机挑选一个宝箱,会发生什么?

假设宝箱中的金额范围是 1000,999,998,...,01000, 999, 998, ..., 0,最高奖金为 10001000。抽中最高奖金的概率是多少?

由于每个具体金额(包括最高奖金 10001000)出现的概率相等,且奖金服从均匀分布,抽中最高奖金的概率可计算如下:

PJackpot=1(最高奖金最低奖金+1)P_{Jackpot} = \frac{1}{(\text{最高奖金} - \text{最低奖金} + 1)}

在这种情况下,最高奖金为 10001000,最低为 00,因此:

PJackpot=1(10000+1)=11001P_{Jackpot} = \frac{1}{(1000 - 0 + 1)} = \frac{1}{1001}

因此,随机挑选一个宝箱恰好装有最高奖金 10001000 的概率为 0.0999%0.1%0.0999\% ≈ 0.1\%。几率确实非常低。

既然追求大奖不太现实,我们不妨降低一点期望。如果我们的目标是至少 800800 的奖金,抽中的概率是多少呢?

我们可以利用均匀分布的公式。对于在 0010001000 之间均匀分布的奖金,其概率密度函数是常数。概率的公式为:

P(aXb)=ba范围P(a \leq X \leq b) = \frac{b - a}{\text{范围}}

在这种情况下,范围从 0010001000,总范围为 10001000。我们要计算区间 80080010001000 的概率,因此:

P(800X1000)=10008001000=2001000=0.2P(800 \leq X \leq 1000) = \frac{1000 - 800}{1000} = \frac{200}{1000} = 0.2

因此,随机挑选一个奖金在 80080010001000 之间的宝箱的概率为 20%20\%

虽然概率显著提高了,但 20%20\% 仍然相对较低。

所以,如果随机挑选一个宝箱并决定保留它,获得高额奖金的几率仍然不大,这显然不是最优策略。

优化

在大多数情况下,我们不知道宝箱内的最高奖金是多少。正如苏格拉底的学生们摘取最大麦穗的故事一样,他们并不知道最大的麦穗有多大。

让我们换一种思路。即使我们不知道最高奖金,但我们知道:如果我们抽取一部分宝箱作为样本,那么样本中出现大奖的概率与在整个集合中出现大奖的概率是相等的。通过抽取一部分宝箱,我们可以根据样本中的最高奖金来估计大奖的值。

设整个集合中的大奖为 MM。由于大奖在宝箱中服从均匀分布,我们可以从宝箱中抽取一个样本,并记录样本中的最高奖金,记为 MM'。显然,这个样本最大值 MM' 会接近整体大奖 MM

抽取一部分宝箱来估计大奖 MM 是可行的,而且抽取的样本越多,MM' 就越接近 MM

然而,样本量不能太小,否则 MM'MM 之间的差距会很大,使得估计失去意义。另一方面,样本量也不能太大,因为剩下的可挑选宝箱会变少,从而降低找到大奖的机会。考虑一个极端的例子:如果从 10001000 个宝箱中抽取 999999 个作为样本,MM' 很可能几乎等于 MM,但只剩一个宝箱可选,抽中大奖的机会就微乎其微了。

因此,平衡样本量与宝箱总数非常重要。是否存在一个最优样本量,使得 MM' 接近 MM,同时之后赢得高额奖金的概率最大?

接下来,我们将用数学方法推导这个「平衡点」。设宝箱总数为 mm,样本量为 rr。我们将求出最优 rr 的表达式。

数学推导

假设共有 NN 个宝箱,我们选取前 rr 个宝箱作为样本。在此情形下,我们的目标是求出使丢弃样本后选中最高奖金概率最大的最优样本量 rr

概率推导

对于固定的 rr,设最高奖金出现在第 kk 个宝箱中。要在丢弃样本后赢得最高奖金,必要条件是最高的第二大奖出现在前 k1k-1 个箱子中,并且具体而言,这个第二大奖还必须出现在样本(前 rr 个箱子)之内。这种情况发生的概率为 rk1\frac{r}{k-1}

这可以用一幅图来直观展示,图中红色箭头表示第二大奖出现的位置:

由此我们推导出如下方程:

P=1Nk=r+1Nrk1=rNk=r+1N1k1P = \frac{1}{N} \sum_{k=r+1}^{N} \frac{r}{k-1} = \frac{r}{N} \sum_{k=r+1}^{N} \frac{1}{k-1}

在这个方程中,1N\frac{1}{N} 表示最高奖金出现在第 kk 个宝箱中的概率,rk1\frac{r}{k-1} 表示第二大奖位于前 rr 个箱子样本中的概率。PP 是丢弃样本后赢得最高奖金的概率。

求和近似

上述方程包含一个调和级数,它没有简单的闭式解,但可以用如下公式近似:

k=1N1k=ln(N)+γ\sum_{k=1}^{N} \frac{1}{k} = \ln(N) + \gamma

其中 ln(N)\ln(N) 是自然对数,γ\gamma 是 Euler 常数。这里,我们要近似从 r+1r+1NN 的求和。为此,我们将和式改写为:

k=r+1N1k1=k=1N(r+1)+11k=k=1Nr1k\sum_{k=r+1}^{N} \frac{1}{k-1} = \sum_{k=1}^{N-(r+1)+1} \frac{1}{k} = \sum_{k=1}^{N-r} \frac{1}{k}

于是,求和从 k=1k=1 开始,沿用同样的调和级数近似:

k=r+1N1k1=(ln(N)+γ)(ln(r)+γ)=ln(N)ln(r)\sum_{k=r+1}^{N} \frac{1}{k-1} = \left( \ln(N) + \gamma \right) - \left( \ln(r) + \gamma \right) = \ln(N) - \ln(r)

最后,利用对数的性质,我们将其化简为:

ln(N)ln(r)=ln(Nr)\ln(N) - \ln(r) = \ln\left(\frac{N}{r}\right)

代入原方程

现在,我们将化简后的和式代入原概率方程:

P=rNln(Nr)P = \frac{r}{N} \ln\left(\frac{N}{r}\right)

接下来,我们引入新变量 x=rNx = \frac{r}{N} 表示样本占全部宝箱的比例,得:

P=xln(1x)P = x \ln\left(\frac{1}{x}\right)

最大化概率

为最大化 PP,我们对 P=xln(1x)P = x \ln\left(\frac{1}{x}\right) 关于 xx 求导:

dPdx=ddx(xln(1x))\frac{dP}{dx} = \frac{d}{dx} \left(x \ln\left(\frac{1}{x}\right)\right)

利用乘积法则:

ddx(uv)=udvdx+vdudx\frac{d}{dx}(uv) = u \frac{dv}{dx} + v \frac{du}{dx}

其中 u=xu = xv=ln(1x)v = \ln\left(\frac{1}{x}\right),我们计算导数:

dudx=1\frac{du}{dx} = 1

dvdx=ddxln(1x)=ddx(ln(x))=1x\frac{dv}{dx} = \frac{d}{dx} \ln\left(\frac{1}{x}\right) = \frac{d}{dx} \left(-\ln(x)\right) = -\frac{1}{x}

将这些代入乘积法则:

dPdx=x(1x)+ln(1x)1=1+ln(1x)\frac{dP}{dx} = x \left(-\frac{1}{x}\right) + \ln\left(\frac{1}{x}\right) \cdot 1 = -1 + \ln\left(\frac{1}{x}\right)

为求最大概率 PP,我们令导数为零:

1+ln(1x)=0-1 + \ln\left(\frac{1}{x}\right) = 0

因此,有:

ln(1x)=1\ln\left(\frac{1}{x}\right) = 1

两边取指数,得:

1x=e\frac{1}{x} = e

因此,x=1ex = \frac{1}{e},也就是说当 rN=1e\frac{r}{N} = \frac{1}{e} 时概率最大。

最大概率

在这个最优点,最大概率为:

P=Pmax=1e0.368P = P_{max} = \frac{1}{e} \approx 0.368

这表明最优策略是:先抽取约占全部宝箱 1e\frac{1}{e}(约 36.8%)的样本,然后选择下一个奖金大于样本中所有奖金值的宝箱。这一策略能使选中最高奖金的机会最大化。

程序模拟

我们可以用 TypeScript 模拟上述过程。

为验证使用该策略赢得最高奖金的概率,我们可以计算获得最高奖金的成功试验次数与总试验次数的比值。下面是用 TypeScript 编写的模拟程序:

function simulateGamblingGame(m: number, x: number, trials: number): number {
  let successCount = 0;

  for (let trial = 0; trial < trials; trial++) {
    const boxes = Array.from({ length: m }, () => Math.random() * x);
    const firstPart = boxes.slice(0, Math.floor(m * 0.37));

    // 记下前 37% 的箱子中的最高奖金
    const p = Math.max(...firstPart);

    // 找出所有箱子中的最高奖金
    const maxPrize = Math.max(...boxes);

    // 从 37% 之后开始检查是否存在高于 p 的奖金
    for (const prize of boxes.slice(Math.floor(m * 0.37))) {
      if (prize > p) {
        if (prize === maxPrize) {
          successCount++;
        }
        break; // 一旦找到更高的奖金即停止
      }
    }
  }

  return successCount / trials; // 返回成功概率
}

// 设置参数
const m = 100; // 宝箱总数
const x = 1000; // 每个宝箱中的最高奖金
const trials = 100000; // 试验次数

const successProbability = simulateGamblingGame(m, x, trials);
console.log(`赢得最高奖金的概率:${successProbability}`);

说明

  1. 参数:
    • m:宝箱总数。
    • x:每个宝箱中的最高奖金。
    • trials:模拟试验次数。试验次数越多,结果越精确。
  2. 模拟过程:
    • 随机生成每个宝箱的奖金。
    • 计算前 37% 的宝箱中的最高奖金(p)。
    • 找出所有宝箱中的最高奖金(maxPrize)。
    • 从第 38% 的宝箱开始,检查是否有高于 p 的奖金,并判断其是否等于 maxPrize
  3. 结果:
    • 返回多次试验后赢得最高奖金的概率。

运行该模拟会得到类似如下的结果:

赢得最高奖金的概率:0.367999

如图所示,赢得最高奖金的概率提高到了约 37%,相比 0.1% 有了显著提升。


为进一步验证,我们把奖金范围按 10%10\% 的增量划分(例如前 10%、前 20% 等),模拟赢得前 t%t\% 奖金的概率。

针对不同奖金范围的修改版 TypeScript 代码

function simulateGamblingGameWithRanges(
  m: number,
  x: number,
  trials: number
): number[] {
  const successCounts = Array(10).fill(0);
  // 用于存储各范围内成功次数的数组

  for (let trial = 0; trial < trials; trial++) {
    const boxes = Array.from({ length: m }, () => Math.random() * x);

    const k = Math.floor(m * 0.37);
    const firstPart = boxes.slice(0, k);

    const p = Math.max(...firstPart);

    let chosenPrize = 0;

    // 找到前 37% 之后第一个大于 p 的宝箱
    for (const prize of boxes.slice(k)) {
      if (prize > p) {
        chosenPrize = prize;
        break;
      }
    }

    // 若没有找到大于 p 的宝箱,则选择最后一个宝箱
    if (chosenPrize === 0) {
      chosenPrize = boxes[boxes.length - 1];
    }

    const sortedBoxes = [...boxes].sort((a, b) => b - a);

    // 判断所选奖金落入的奖金范围
    for (let i = 1; i <= 9; i++) {
      const thresholdPrize = sortedBoxes[Math.floor((m * i * 10) / 100)];
      if (chosenPrize >= thresholdPrize) {
        successCounts[i - 1]++;
      }
    }

    // 前 100% 的奖金必定被选中,因此增加此计数
    successCounts[9]++;
  }

  // 将计数转换为概率
  const successProbabilities = successCounts.map((count) => count / trials);

  return successProbabilities;
}

// 设置参数
const m = 100; // 宝箱数量
const x = 1000; // 最高奖金
const trials = 100000; // 试验次数

const successProbabilities = simulateGamblingGameWithRanges(m, x, trials);

// 输出各奖金范围的概率
for (let i = 1; i <= 10; i++) {
  console.log(
    `赢得前 ${i * 10}% 奖金的概率:${(
      successProbabilities[i - 1] * 100
    ).toFixed(2)}%`
  );
}

程序运行结果

赢得前 10% 奖金的概率:66.96%
赢得前 20% 奖金的概率:70.67%
赢得前 30% 奖金的概率:74.42%
赢得前 40% 奖金的概率:78.06%
赢得前 50% 奖金的概率:81.70%
赢得前 60% 奖金的概率:85.45%
赢得前 70% 奖金的概率:89.14%
赢得前 80% 奖金的概率:92.84%
赢得前 90% 奖金的概率:96.60%
赢得前 100% 奖金的概率:100.00%

我们看到,使用这一策略,我们能够最大化获得高额奖金的机会。

结论

模拟验证了:先选取 37% 的宝箱,然后选择下一个奖金高于前 37% 中最高奖金的宝箱,是最优策略。这一策略使赢得最高奖金的概率最大,即著名的 37% 法则。

这一策略也可以应用于现实生活中的场景,例如在不确定的情况下作出最优选择。