【随机】三门问题

大家好,我是小白学编程。

最近同事问我一个问题,就是经典的三门问题,之前我也听过这个问题,但是没有去想过。今天用代码做了一个实验统计,统计结果如下:

一、问题

        问题是这样的,有三道门,每道门后面放一样东西,分别是汽车、羊、羊。出题者是知道所有放置的位置的,选择者不知道放置的位置。当选择者选好一道门之后,出题者会打开另外一道后面放着羊的门,这时问选择者换不换门。意思就是换门选择到汽车的几率大还是不换门选择的汽车的几率大?那么,如果你是选择者,你会选择换门吗?

二、错误引导

        你是否会有这样的想法?

        当第一次选择时,门后面是汽车的概率是 1/3 ,当选择好之后,这时出题者打开一道后面是羊的门。打开这道门对你刚刚选择的门没有任何影响,刚刚选择的门后面放的是什么,现在放的还是什么,结果不会发生变化。假如现在重新再选一次,排除掉打开的那道门,还剩两道门,那么选择则到汽车的概率就是 1/2 。但是,题目中说的是换门,那么可以做两个假设:

三道门

        假设一:第一次选择了 A 门,此时出题者打开的是 C 门,C门后面是羊,这时,如果选择者进行换门,则会换为 B 门;如果不换门,还是 A 门

        假设二:第一次选择了 B 门,此时出题者打开的是 C 门,C门后面是羊,这时,如果选择者进行换门,则会换为 A 门;如果不换门,还是 B 门

打开一道门

        那么,假设一中的换门的结果,和假设二中的不换结果是一样的;假设二中的换门的结果,和假设一中的不换的结果式样的。而且第一次选择哪个门都一样,所以换不换门结果都是一样的。

        如果有这样的想法,那就时进入了误区,这个想法是不对的!

三、正确分析

        当第一次选择时,不论选哪道门,选中汽车的概率都是 1/3 ,选中羊的概率羊的概率都是 2/3。那也就是说第一次选择大概率是错的,记住,第一次选则一道门,比如 A 门,大概率是错的。那么此时打开了 C 门,C 门后面是羊,那就剩下 B 门后面可能出现汽车了。既然 A 门大概率是错的,那么 B 门就大概率是对的,所以选择换门。

        再换一种说法,第一次选择,不论选择哪道门,后面是汽车的概率都是 1/3 ,比如选择了 A 门。当选择一道门之后,出题人打开一道门,比如 C 门,C 门后面是羊,那么你知道了 C 门后面

打开门之前

打开门之后

的结果是羊,那么 C 门后面是汽车的概率就是 0 ,那么 B 门后面出现汽车的概率就是 2/3。

四、结论

        打开门之后,肯定要选择换门,换门可以选则到汽车的概率大

五、实验代码

        前面分析的可能有人还是疑惑,有点不敢相信,那么接下来就用代码测试一下,模拟做五轮实验进行比较,每轮做一千次选择

1、代码

    private static final String CAR = "汽车";

    @Test
    public void test1(){
        //换门的成功概率
        List<String> changeRate = Lists.newArrayList();
        //不换门的成功概率
        List<String> notChangeRate = Lists.newArrayList();
        for(int i = 0;i < 5; i++){
            int successChange = 0;
            int successNotChange = 0;
            for(int j = 0;j < 1000;j++){
                if(threeDoor(true)){
                    successChange++;
                }
                if(threeDoor(false)){
                    successNotChange++;
                }
            }
            String resultChange = successChange * 100.0 / 1000 + "%";
            changeRate.add(resultChange);
            String resultNotChange = successNotChange * 100.0 / 1000 + "%";
            notChangeRate.add(resultNotChange);
        }
        System.out.println("对三门问题做调研,换门做五次统计,不换门做五次统计,每次统计做1000次实验,成功选中汽车的概率输出结果如下:");
        System.out.println("—————————————————————————————————————————————————————————————————————————————————————————");
        for(int i = 0; i <= 5;i++){
            if(i == 0){
                System.out.print("|\t\t|");
            } else {
                System.out.print("\t第 " + i + " 次统计\t|");
            }
        }
        System.out.println("\n—————————————————————————————————————————————————————————————————————————————————————————");
        for(int i = 0; i <= 5;i++){
            if(i == 0){
                System.out.print("|换门\t|");
            } else {
                System.out.print("\t" + changeRate.get(i - 1) + "\t\t|");
            }
        }
        System.out.println("\n—————————————————————————————————————————————————————————————————————————————————————————");
        for(int i = 0; i <= 5;i++){
            if(i == 0){
                System.out.print("|不换门\t|");
            } else {
                System.out.print("\t" + notChangeRate.get(i - 1) + "\t\t|");
            }
        }
        System.out.println("\n—————————————————————————————————————————————————————————————————————————————————————————");
    }

    /**
     *  选择实验
     * @param changeFlag    true 为换门,false 坚持不换门
     * @return
     */
    public boolean threeDoor(boolean changeFlag){
        //已知的门后放置的内容
        List<String> list = Lists.newArrayList("汽车","羊","羊");
        //三道门
        List<String> threeDoors = Lists.newArrayList();
        Random rand = new Random();
        //随机向门后放东西
        for(int i = 3; i > 0; i--){
            int index = rand.nextInt(9 + (3 - i)) % i;
            String door = list.get(index);
            list.remove(index);
            threeDoors.add(door);
        }
        //获取放汽车的门
        int carDoor = threeDoors.indexOf(CAR);
        //随机选一道门
        int selectedDoor = rand.nextInt(9) % 3;
        //可以打开的门
        List<Integer> enableOpenDoors = Lists.newArrayList();
        for(int i = 0;i <= 2; i++){
            if(carDoor != i && selectedDoor != i){
                enableOpenDoors.add(i);
            }
        }
        int size = enableOpenDoors.size();
        int openIndex = rand.nextInt(9 + (3 - size)) % size;
        //打开的门
        int openDoor = enableOpenDoors.get(openIndex);

        int resultDoor = selectedDoor;
        if(changeFlag){
            //换门
            for (int i = 0; i <= 2; i++){
                if(i != selectedDoor && i != openDoor){
                    resultDoor = i;
                    break;
                }
            }
        }
        //打开选择的门
        String result = threeDoors.get(resultDoor);
        return result.equals(CAR);
    }

2、实验测试结果

我们不能改变过去,但是可以选择如何面对未来

我觉着这问题还挺有意思的,不知道你感觉如何

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值