假设你正在参加一个游戏节目,你被要求在三扇门中选择一扇。其中一扇后面有一辆车,其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后,事先知道门后面有什么的主持人,开启了另一扇后面有山羊的门,假设是三号门。然后他问你:“你想选择二号门吗?”,此时,改变你的选择对你会是更好的选择吗?
这就是著名的“蒙提霍尔问题”,也被称为“三囚犯问题”或者“贝特朗箱子悖论”。后来的研究者们对问题做出了更确切的描述:
参赛者在三扇门中挑选一扇。他并不知道内里有什么。 主持人知道每扇门后面有什么。 主持人必须开启剩下的其中一扇门,并且必须提供换门的机会。 主持人永远都会挑一扇有山羊的门。 如果参赛者挑了一扇有山羊的门,主持人必须挑另一扇有山羊的门。 如果参赛者挑了一扇有汽车的门,主持人随机在另外两扇门中挑一扇有山羊的门。 参赛者会被问是否保持他的原来选择,还是转而选择剩下的那一道门。
虽然答案已有定论,下面还是用Python来模拟这个选择的过程。此程序假设一个门后有羊,两个门后是空的,随机生成各种排列,重复主持人和参赛者的各种选择多次,来验证参赛者选择换门后得到羊的机率:
#-*-coding:gbk -*- import random class ThreeDoor(object): doors=[] #初始化门结构[[0,0],[0,0],[0,0]],第一维用来放羊,第二维用来记录选手和主持人的选择。每个门后是否有羊(1有,0无),是否选择此门(未选择0,选手选1,主持人选2) doorcount=3 def __init__(self): #初始化三个门[[0,0],[0,0],[0,0]],然后随机往一个门后放只羊(置为1),如[[0,0],[1,0],[0,0]],表示随机往第二门后放了只羊 self.doors=[] which=random.randint(1,self.doorcount) for a in range(1,self.doorcount+1): if (a==which): self.doors.append([1,0]) else: self.doors.append([0,0]) print('init:\n',[ a[0] for a in self.doors],'\n',[ a[1] for a in self.doors]) def __del__(self): self.doors=[] def choice1(self): #选手在3个门中随机选择1个门(置为1):[[0,0],[1,0],[0,1]]表示选手选择了第3个门 ch1=random.randint(1,self.doorcount) self.doors[ch1-1][1]=1 print('choice1:\n',[ a[0] for a in self.doors],'\n',[ a[1] for a in self.doors]) def choice2(self): #主持人选择1个没有羊的门(置为2)(若有羊的门已被选手选到,则在剩下2门中随机选1个门)如:[[0,2],[1,0],[0,1]] set2=list(map(lambda x,y:x+y,[a[0] for a in self.doors],[a[1] for a in self.doors])) print('set2:',set2) if max(set2)==2: w=random.randint(1,self.doorcount-1) b=[ i for (i,item) in enumerate(set2,start=0) if item!=2] self.doors[b[w-1]][1]=2 elif max(set2)==1: self.doors[set2.index(0)][1]=2 print('choice2:\n',[ a[0] for a in self.doors],'\n',[ a[1] for a in self.doors]) def summ(self): #此时还有1个门选手和主持人都没有选。计算此门后有羊的机率(也就是选手改选此门后得到羊的机率) return self.doors[[a[1] for a in self.doors].index(0)][0] #只需返回未选的门(列表第二维值为0的索引,因为选手选的为1,而主持人选的为2)的第一维值是否为1(1表示有羊) if __name__=='__main__': success=0 #换门后命中羊的次数 testcount=100000 #总测试次数 print('总测试次数:',testcount) for a in range(0,testcount): print('第%d次测试:'%a) n=ThreeDoor() n.choice1() n.choice2() success=success+n.summ() print('当前换门得羊成功率%f'%(success/(a+1))) del n
程序设置了模拟10万次,其实运行1千次跟10万次结果不会有太大的出入:
第99998次测试: init: [0, 1, 0] [0, 0, 0] choice1: [0, 1, 0] [0, 1, 0] choice2: [0, 1, 0] [2, 1, 0] 当前换门得羊成功率0.665697 第99999次测试: init: [0, 0, 1] [0, 0, 0] choice1: [0, 0, 1] [0, 0, 1] choice2: [0, 0, 1] [0, 2, 1] 当前换门得羊成功率0.665690
可看到,验证的结果跟此问题的答案一致,参赛者在主持人询问时选择换门,确实能把命中羊的机率提高到2/3。
原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/2220.html