跑上百万次代码,终于把三门问题验证了

苦逼的码农

共 3300字,需浏览 7分钟

 ·

2020-03-03 23:24

帅地玩编程公众号后台回复 剑指offer,送你一本剑指offer书籍

来源:小浩算法

作者:程序员浩哥


7da8b259dc36f34a0b742919b0ae6489.webp

三门问题(Monty Hall problem)亦称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论,出自美国的电视游戏节目Let's Make a Deal。今天为大家进行完整分析。


话不多说,直接看题目。



01三门问题


653726ee3ca3b6c9edd7eca7d89a688f.webp三门问题:参赛者的面前有三扇关闭着的门,其中一扇的后面是天使,选中后天使会达成你的一个愿望,而另外两扇门后面则是恶魔,选中就会死亡。 3470f8d8eb61c6bd2a40c38c43689b35.webp

当你选定了一扇门,但未去开启它的时候,上帝会开启剩下两扇门中的一扇,露出其中一只恶魔。(上帝是全能的,必会打开恶魔门)随后上帝会问你要不要更换选择,选另一扇仍然关着的门。


7567c42a004cd57ab4bd7605ba6a6952.webp


02普通人的直觉

4151f473a1d85ef9c9a150fd2824a820.webp

按照常理,参赛者在做出最开始的决定时,对三扇门后面的事情一无所知,因此他选择正确的概率是1/3,这个应该大家都可以想到。


接下来,主持人排除掉了一个错误答案(有恶魔的门),于是剩下的两扇门必然是一扇是天使,一扇是恶魔,那么此时无论选择哪一扇门,胜率都是1/2,依然合乎直觉。


所以你作为参赛者,你会认为换不换都无必要,获胜概率均为1/2。但是,真的是这样吗?


1b0dfb83fc686ef6f4f83b46249b8e76.webp


03题目分析

6c0374fc45980d5dbe9495bf52bead0a.webp

正确的答案是,如果你选择了换,碰见天使的概率会高达2/3,而不不换的话,碰见天使的概率只有1/3。怎么来的?


我们用一个很通俗的方法,能让你一听就懂。首先刚开始选择的一扇门的概率为1/3,而另外两扇门的总概率为2/3。


74a837ab211ee6cc9e809285d68fa8e0.webp


现在上帝打开了其中一扇为恶魔的门,我们知道这个门后面不会再有天使,所以相当于这部分概率被第三个门持有。



63a3ef3aef350dd20d9845f3a372b4e5.webp


剩下的那扇门的概率(2/3)相当于刚开始选择的门(1/3)的二倍。所以我们得换。


如果还没有听懂。我们可以假设有一百扇门,里边有99只都是恶魔。现在你随机选择一扇门,选择到天使的概率是1/100。


789e18e960594cbe246211099123280b.webp


这时,上帝打开其中的98扇,里边都是恶魔。这时候就相当于99/100的概率都集中在了另一扇门里。自然,我们需要选择换。


cf7aac79bcc821d17d5484674cc3ab4e.webp


04贝叶斯证明 代码证明

6c0374fc45980d5dbe9495bf52bead0a.webp

为了验证结果,我用代码跑了一百万次。什么?用贝叶斯分析分析!太俗(请隔壁去找李永乐老师),咱们还是直接上代码。

 1func main() {
2    //换门遇见天使的次数和不换门遇见天使的次数
3    changeAngelCount, unchangeAngelCount := 00
4    for i := 0; i < 1000000; i++ {
5        //门的总数
6        doors := []int{012}
7        //天使门和选中的门
8        angelDoor, selectedDoor := rand.Intn(3), rand.Intn(3)
9        //上帝移除一扇恶魔门
10        for j := 0; j < len(doors); j++ {
11            if doors[j] != selectedDoor && doors[j] != angelDoor {
12                doors = append(doors[:j], doors[j+1:]...)
13                break
14            }
15        }
16        //统计
17        if selectedDoor == angelDoor {
18            unchangeAngelCount++
19        } else {
20            changeAngelCount++
21        }
22    }
23    fmt.Println("不换门遇见天使次数:", unchangeAngelCount, "比例:", (float32(unchangeAngelCount) / 1000000))
24    fmt.Println("换门遇见天使次数:", changeAngelCount, "比例:", (float32(changeAngelCount) / 1000000))
25}


跑了一百万次,结果当然不让我们失望!


3ebe24ec6bea20fa67c6948209dbb145.webp



推荐阅读

全部文章分类与整理(算法+数据结构+计算机基础),持续更新

【吐血整理】那些让你起飞的计算机基础知识:学什么,怎么学?

普普通通,我的三年大学

写公众号15个月以来,这一路上的学习与收获

历经两个月,我的秋招之路结束了!

2020 第一篇原创 | 我是如何让自己变的更加优秀的?

浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报