三门问题来源于一个娱乐节目。节目中有一位参与者和一位主持人,在参与者的面前有三扇关闭的门,其中两扇门的后面是空的,剩下一扇门后是一辆法拉利跑车。当参赛者选定了一扇门,但未去开启它的时候,节目主持人开启剩下两扇门的其中一扇,是空门。主持人其后会问参赛者要不要换另一扇仍然关上的门。

本质问题是换另一扇门会否增加参赛者赢得汽车的机会率?网上统一的答案是“会”,但是我发现有一个很重要的一点都被网上的文章忽略了,主持人他知道中奖的门吗?

一、代码验证

此处列举一个网上的 Java 代码验证问题的实例:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        // 测试次数
        int n = 10000;
        //换门的获奖总次数
        int changeWinCount = 0;
        //不换门的获奖总次数
        int unChangeWinCount = 0;
        Random random = new Random();
        for (int i = 0; i < n; i++) {
            // 获奖的门
            int bonusDoor = random.nextInt(3);
            // 选中的门
            int selectedDoor = random.nextInt(3);
            // 如果选中的门就是获奖的门,那么不换门得奖,反之换门可以得奖
            if (selectedDoor == bonusDoor) {
                unChangeWinCount++;
            } else {
                changeWinCount++;
            }
        }
        System.out.println("不换门获奖总次数:" + unChangeWinCount + ",比例:" + (float) unChangeWinCount / (changeWinCount + unChangeWinCount));
        System.out.println("换门获奖总次数:" + changeWinCount + ",比例:" + (float) changeWinCount / (changeWinCount + unChangeWinCount));
    }
}

这个程序的运行输出大致为:

不换门获奖总次数:3336,比例:0.3336
换门获奖总次数:6664,比例:0.6664

根据这个结果,我们很容易就可以得出结论,不换门的获奖概率为 1/3 ,换门的获奖概率为 2/3

但是事实是这样嘛,在上面的案例中并没有详细的考虑到主持人开门的细节。

二、主持人是如何开门的?

在上面的案例代码中仅判断了选中的门是否是中奖的门,稍微有些统计常识的同学都可以立即的出中奖概率为 1/3 的结论。但是这个三门问题应该还应该更加细化的考虑一点,主持人知道中奖的门是哪个吗?

  • 主持人知道: 主持人知道中奖的门,可以准确的打开未中奖的门,可以无须考虑主持人是否开门。
  • 主持人不知道: 主持人不知道中奖的门是哪个,有一定的几率打开的是中奖的门,那么这局游戏应该重开。而主持人打开中奖的门的概率是 2/3 * 1/2 = 1/3

当主持人不知道中奖门时的验证代码:

import java.util.*;

public class Test {
    public static void main(String[] args) {
        // 测试次数
        int n = 10000;
        //换门的获奖总次数
        int changeWinCount = 0;
        //不换门的获奖总次数
        int unChangeWinCount = 0;
        Random random = new Random();
        for (int i = 0; i < n; i++) {
|+             // 主持人可打开的门
|+             List<Integer> doors = new ArrayList<>(Arrays.asList(0, 1, 2));
            // 获奖的门
            int bonusDoor = random.nextInt(3);
            // 选中的门
            int selectedDoor = random.nextInt(3);
|+             // 选中的门不可打开
|+             doors.remove(selectedDoor);
|+             // 剩余的两个门中主持人选中一个打开
|+             int compereSelectedDoor = doors.get(random.nextInt(2));
|+             // 如果主持人选中中奖的门则作废
|+             if (compereSelectedDoor == bonusDoor) {
|+                 continue;
|+             }
            // 如果参与者选中的门就是获奖的门,那么不换门得奖,反之换门可以得奖
            if (selectedDoor == bonusDoor) {
                unChangeWinCount++;
            } else {
                changeWinCount++;
            }
        }
        System.out.println("不换门获奖总次数:" + unChangeWinCount + ",比例:" + (float) unChangeWinCount / (changeWinCount + unChangeWinCount));
        System.out.println("换门获奖总次数:" + changeWinCount + ",比例:" + (float) changeWinCount / (changeWinCount + unChangeWinCount));
    }
}

这个程序的运行输出大致为:

不换门获奖总次数:3380,比例:0.5047036
换门获奖总次数:3317,比例:0.4952964

通过以上结果可以看到,有 1/3 的局数被作废了,换门和不换门的获奖概率一致,都为 1/3

三、总结

这道题的重点就在于主持人选中中间门时的处理上,网上的代码示例都未考虑到主持人有概率选到中奖门这个情况。或者说都默认主持人知道中奖门,不会选错。于是未将主持人选中中间门的概率排除掉,并将这个概率合并到了换门获奖的概率中。所以有了 1/32/3 的这个中奖率的差别。

PS:这个三门问题是在主持人知道中间门的前提下进行的。本身这是一个很简单的概率问题,只是一些文章作者没有注意到这一点,并没有说明主持人知道中奖门的前提,直接就说不换门和换门的中奖概率是 1/32/3 ,这才导致了争议。