三门问题——亦称为蒙提霍尔问题,出自美国的电视游戏节目Let's Make a Deal。问题的名字来自该节目的主持人蒙提·霍尔(Monty Hall)【2】。问题是这样的:
参赛者面前有三扇关闭着的门,其中一扇的后面是一辆汽车,选中后面有车的那扇门就可以赢得该汽车,
而另外两扇门后面则各藏有一只山羊。当参赛者选定了一扇门,但未去开启它的时候,主持人会开启剩
下两扇门中的一扇,露出其中一只山羊。主持人其后会问参赛者要不要更换选择,选另一扇仍然关着的门。
据说此节目一经播出就引起了一场热烈的讨论,有人说应该换,有人认为换不换都一样。主持人给出的答案是应该换,并在下一期的节目中给出了一个分析表格用来说明她的理由。但这下反对的声音更大了,在几千封来信中,反对者达到了9成。【1】
在所有认为该换和不该换的争论中,正反两方形成了两种对立的观点。
一种是认为不换的中奖几率是1/3,换的话将有2/3的几率中奖,因此当然应该换。因为:
根据参赛者的选择,一共有下面三种可能情况(两只山羊分别称为山羊A和山羊B):
(1) 参赛者选择山羊A,主持人选择山羊B;
(2) 参赛者选择山羊B,主持人选择山羊A;
(3) 参赛者选择了汽车,主持人选择两只山羊的任何一只
三种情况几率各为1/3,如果换的话,前两种都会中奖,仅第三种不会中奖。所以选择换的中奖概率为2/3,不换几率只有1/3。
下面再来看看“反方”观点,这种观点认为换不换都一样,几率都是50%。因为:
当参赛者选择一扇门时,他中奖的几率确实只有1/3。但当主持人帮忙排除掉一只山羊时,
车要么在参赛者所选的这个门中,要么在剩下的未被选择的那扇门中。此时参赛者变更选
择的话,当然中奖几率会提升到1/2。
还可以换一个角度来理解。即使他没有变更选择,他实际上也做出了选择,只是选择的是“不变更”而已。虽然选择的是“不变”,但不代表他的几率不变。整个过程重新组织一下会更容易看明白:
(1) 参赛者选了一扇门但不打开
(2) 此时主持人在剩下的两扇门中选出一扇后面是山羊的门
(3) 然后参赛者在剩下的两扇门中再次选择了第一次选择的门
所以,他选到车的概率为50%。
当然,还有很多“非主流”的观点,但都经不起推敲,这里不再赘述,感兴趣的可以去搜一下。
分析
两种观点乍一看好像都很有道理,但它们之中肯定有一个是错误的。我认为第一种是正确的,因此分析的重点是解释为什么另一种答案是错误的。并且后面我会编写程序来验证答案。
为什么第二种观点是错误的呢?这是因为当我们第一次做出选择时,所基于的样本总数为3,此时选定的门后面为汽车的几率是1/3。并且选定后这一几率不会再改变(第二种答案正是基于几率会变的观点),因为对于已发生的事件来说,后来发生的事件是不可能影响它的几率的。
千万不要误解了上面这句话,这里谈到的是几率,是多次事件的统计结果,并不是确定的一次已发生事件的结果。例如,当把剩下的两个门都打开后,就能够确定//代码效果参考:http://www.jhylw.com.cn/154239361.html
第一扇门后面是否为汽车,但第一扇门的“几率”会因此而改变吗?不会,因为此时我们在谈的是特定一次的结果,而不是几率。如果我们将此过程重复很多次,每次选择一扇门之后都通过另外2扇门来判断这扇门后面是不是汽车,我们会发现,此时得到的几率仍然为1/3。第二种答案之所以是错的,还在于它搞错了一件事情,当我们说“当我们做出选择时,几率就随之确定了”这句话时,实际上是在说“三扇门中任何一扇门后面是汽车的几率都是1/3”,而不是“我们的选择决定了这件事的几率”。我想很多人都搞错了这一点,一件事的发生几率是由事物的本质规律决定的,并不会因我们人类的意志为转移。
所以第一次选择某个门时,此时的几率是确定的1/3,当主持人排除掉一扇门之后,第一扇门的几率绝不会因此而改变,必然仍然是1/3。也许你还有点绕不过这个弯,为此我们来做一个思维实验:
假设你是参赛者,台上放着三个盒子,其中一个盒子中有奖品,另外两个是空的。
你首先从三个盒子中随便选择一个,然后把所选的盒子抱到一间密封的屋子里面,
但不允许打开盒子,此时主持人在剩下的两个盒子中打开没有奖品的那个。试问,
你怀里的盒子的中奖几率会因此而改变吗?
是不是有点“薛定谔的猫”的味道?薛定谔的猫是针对量子态的,其真相我们还不得而知,但对宏观世界来说,我可以负责任地说,盒子中奖的几率绝对不会改变。
可能你现在已经能够接受第一次选择的盒子的中奖几率不会改变这一结论了。但我知道你肯定还有最后一个疑问,如果不把这个疑问弄清楚,你永远也不可能真正弄明白这个问题。为此,我们来进行第二个思维实验:
假设有2个参赛者A和B,参赛者A按照原来的流程先选择一扇门,此时主持人把一
扇有山羊的门排除掉了。此时又来了一个参赛者B,他并不知道之前发生的事情,
此时他在剩下的两扇门中随便选择一扇门,他的中奖几率不应该是1/2吗?也就是
说,剩下的两扇门的几率不应该都是1/2吗?
可能你已经看出来了,这实际上//代码效果参考:http://www.jhylw.com.cn/543936857.html
就是对第二种观点的另一种表述方式,只是把参赛者表述成了A和B 2个人。同样的2扇门,A和B看到的几率却不一样,这可能吗?前面说过,几率实际上是事物的固有规律,并不以我们的意志为转移。或者说,世间本没有“几率”这个东西,每一件事情都是孤立的、确定的(这里仅讨论宏观),几率只是经过我们人类的抽象和总结后得到的一个概念。每一次,当三扇门被放到台上时,它的结果都是确定的,而且任何2次相互之间都不会有任何影响。这就像抛硬币一样,虽然你可能已经连续抛了100次正面,但你仍然无法肯定下一次是正面还是反面。
回到参赛者A和B的问题上来。他们俩到底哪一个是正确的呢?
答案是2人都对。
但一扇门的几率怎么可能即是1/3又是1/2呢?这是因为在整个过程中,A比B多掌握了一点信息,A了解到的是:
剩下的2扇门中被排除了一扇
而对B来说,他看到的是:
三扇门中被排除了一扇
正是因为掌握的信息是不对称的,因此A能够比B更加准确地做出判断,进而影响到决策的正确性。也就是说,A“更加正确”,B虽然也没有错(题目给他的信息只有那么多,他只能得出对他来说最为正确的判断),但他却比A要稍逊一筹。如果抽奖重复很多次,A每次都更换选择而B是随机选择,那么A将大约比B多2/3-1/2=1/6的中奖机会。更有甚者,如果A每次都更换选择,而B是一个认死理的人,他每次都非要跟A反着干,那么结果将会更惨。
如果说了这么多你心里还保留着一点点疑惑的话,那我再来说一个思维实验,这个思维实验是我的“终极武器”,每次跟人讨论这个问题的时候,只要一说出这个实验,争论立马就平息了。这个实验是这样的:
假设你买了一张彩票,此时上帝出现了,祂对你说,小伙子,看到你买了这么多次
连一次5块的都没中过,这次我决定为你排除掉一半不能中奖的号码。
那么请问,在上帝帮你排除掉那些号码后,你手里这张彩票的中奖几率会因此而变
大吗?如果此时让你再买一张,你的中奖几率会变大吗?
我想答案是不言而喻的。
程序模拟
下面我们用程序来模拟一下,看看到底是怎样的。
int totalTimes = 1000000;
int bingo = 0;
boolean【】 boxes;
for (int i = 0; i < totalTimes; i++) { // loop 1 million times
boxes = new boolean【】 {false, false, false};
boxes【random(3)】 = true;
int myChoice = random(3);
int hostChoice = openNoPrizeOne(boxes, myChoice);
// 判断另一个盒子是否中奖等同于判断开始选的盒子没有中奖
if (!boxes【myChoice】) {
bingo++;
}
}
// 更换选择的中奖几率
double ratio = (double) bingo 100 / totalTimes;
System.out.println("主持人帮忙排除一个山羊:" + ratio + "%");
return ratio;
其中,random()方法用来生成一个小于参数的随机非负整数。openNoPrizeOne()用来在剩下的门中排除掉一个山羊。
运行这段程序,可以发现最后的结果确实在2/3附近,例如下面是某次运行的结果:
下面再来看看上面第二个思维实验中,参赛者A和参赛者B的几率各是多少:
int totalTimes = 1000000;
int bingoA = 0;
int bingoB = 0;
boolean【】 boxes;
for (int i = 0; i < totalTimes; i++) { // loop 1 million times
boxes = new boolean【】 {false, false, false};
boxes【random(3)】 = true;
int aChoice = random(3);
int hostChoice = openNoPrizeOne(boxes, aChoice);
// 判断另一个盒子是否中奖等同于判断开始选的盒子没有中奖
if (!boxes【aChoice】) {
bingoA++;
}
// 参赛者B各有1/2的几率选择A所选的和剩下的那扇门
boolean isChoiceSameAsA = (random(2) == 1);
if (isChoiceSameAsA && boxes【aChoice】
|| !isChoiceSameAsA && !boxes【aChoice】) {
bingoB++;
}
}
// 更换选择后A的中奖几率
double ratioA = (double) bingoA 100 / totalTimes;
// 随机做出选择的B的中奖几率
double ratioB = (double) bingoB 100 / totalTimes;
System.out.println("主持人帮忙排除一个山羊,参赛者A:" + ratioA + "%,参赛者B:" + ratioB + "%");
return new double【】 {ratioA, ratioB};
下面是某次运行结果:
从代码中我们可以明显地看出(参考判断B是否中奖的if语句):对参赛者B来说,并不是剩下的两扇门的中奖几率都为1/2,而是当我们在两扇门中随机选择一扇时的总中奖几率为1/2。也就是说,B的随机选择“调匀”了两扇门的几率,实际上此时他的中奖几率为:
1/2 1/3 + 1/2 * 2/3
完整代码
参考资料
【1】
【2】
【3】