惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
L
LINUX DO - 热门话题
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
D
Docker
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
T
Tenable Blog
P
Privacy International News Feed
Google DeepMind News
Google DeepMind News
小众软件
小众软件
Cisco Talos Blog
Cisco Talos Blog
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
The Hacker News
The Hacker News
Project Zero
Project Zero
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
Jina AI
Jina AI
Cyberwarzone
Cyberwarzone
The Register - Security
The Register - Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
U
Unit 42
Scott Helme
Scott Helme
A
About on SuperTechFans
WordPress大学
WordPress大学
F
Fortinet All Blogs
大猫的无限游戏
大猫的无限游戏
G
GRAHAM CLULEY
Latest news
Latest news
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Schneier on Security

博客园 - 长沙游学者

填坑 Plugin 'mysql_native_password' is not loaded 裁员相关法律知识 自己写了个截图工具 .net操作oracle,一定要用管理员身份运行 visual studio 啊,切记切记,免得报奇怪的错误。 基于 bootstrap 的 vue 分页组件 前端UI框架《Angulr》入门 EF 中 Code First 的数据迁移以及创建视图 AmazeUI(妹子UI)中CSS组件、JS插件、Web组件的区别 Oracle自动备份.bat 最新更新(支持Win10了) 总结一下Android中主题(Theme)的正确玩法 并不优雅 深入分析结构体——结构体里有属性必须new才能使用? TableEx 小更新 本地包含的JS 原创的java数据访问框架 java十宗罪 Oracle自动备份.bat 更新 C++ 方块游戏小更新 Oracle自动备份.bat
思考:有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后,主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门,现在主持人问你,要不要换个门,请问你换还是不换?
长沙游学者 · 2015-07-02 · via 博客园 - 长沙游学者

题目是这样的:

有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后,主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门,现在主持人问你,要不要换个门,请问你换还是不换?

起初我以为换与不换都是二分之一的机率,后来,我写了一个程序来证实,发现还是要换的,换是三分之二的中奖机率,不换是三分之一的中奖机率,差很多。

直接看我的测试结果吧:

这是C语言编写的程序,测试的结果。(要解答这个题目,其实和什么编程语言无关)

这是C#语言编写的程序,测试的结果。(要解答这个题目,其实和什么编程语言无关)

这是Java语言编写的程序,测试的结果。(要解答这个题目,其实和什么编程语言无关)

多次测试的结果显示,如果换门的话选中目标门的机率大多了。

当然,采样20次,有点少,那我们就来进行1000次测试,看看结果又如何。

当测试1000次时,就可以明显的发现,不换门的中奖机率是3/1,而换门的中奖机率是3/2,差别很大。

以下是C、C#、Java三种不同语言编写的测试代码:

一、C语言测试代码

  1 #include <stdio.h>
  2 #include <time.h>
  3 #include <stdlib.h>
  4 
  5 //有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后
  6 //主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门
  7 //现在主持人问你,要不要换个门,请问你换还是不换?
  8  9 
 10 //测试(总次数, 换门)
 11 void test(int max, int change);
 12 
 13 //入口函数
 14 void main()
 15 {
 16     //各自测试的次数
 17     int count = 20;
 18 
 19     //初始化随机种子
 20     srand((unsigned)time(NULL));
 21 
 22     //不换门测试
 23     printf("不换门测试:\n");
 24     test(count, 0);
 25 
 26     //换门测试
 27     printf("换门测试:\n");
 28     test(count, 1);
 29 }
 30 
 31 //测试(总次数, 换门)
 32 void test(int max, int change)
 33 {
 34 
 35     //max    次数:测试的总次数
 36     //change 换门: 0不换  1换门
 37 
 38     int i;        //循环因子
 39     int m;        //目标:本次中奖的目标数字
 40     int c;        //初选:本次选手初次选择的数字
 41     int x;        //选择:本次选手最终选择的数字
 42     int p;        //排除:主持人排除掉没奖的数字
 43     int z = 0;    //中奖:中奖的总次数
 44 
 45     //循环多次模拟换门测试
 46     for (i=0; i<max; i++)
 47     {
 48         m = rand()%3; //目标:本次中奖的目标数字
 49         c = rand()%3; //初选:本次选手初次选择的数字
 50         
 51         //求出主持人要排除的数字
 52         if(m==c)
 53         {
 54             //选手选择了一个有奖品的,主持人从另外两个没奖品当中随机排除掉一下
 55             p = rand()%2;  //产生  false or true
 56             switch(c)
 57             {
 58             case 0:  //要排除的是:2 or 1
 59                 p = p?2:1;
 60                 break;
 61             case 1:  //要排除的是:2 or 0
 62                 p = p?2:0;
 63                 break;
 64             case 2:  //要排除的是:1 or 0
 65                 p = p?1:0;
 66                 break;;
 67             }
 68         }
 69         else
 70         {
 71             //选手选择了一个没奖品的,主持人排除另一个没奖品的
 72             //3-(m+c) = p
 73             //3-(0+1) = 2
 74             //3-(0+2) = 1
 75             //3-(1+2) = 0
 76             p = 3-(m+c);            
 77         }
 78         
 79         //决定终选
 80         if(change)
 81         {//换门
 82             //x=3-(p+c)
 83             //x=3-(0+1) = 2
 84             //x=3-(0+2) = 1
 85             //x=3-(1+2) = 0
 86             x = 3-(p+c);  //换个门
 87         }
 88         else
 89         {//不换门
 90             x = c;  //最终选择和初次选择一样
 91         }
 92         
 93         //结果
 94         printf("第%02d次  初选的是:%d, 目标是:%d, 排除的是:%d, 终选的是:%d", i+1, c, m, p, x);
 95         if(m==x)
 96         {
 97             //中奖了
 98             z++;
 99             printf("  (中奖了)\n");
100         }
101         else
102         {
103             //没中奖
104             printf("\n");
105         }
106     }
107     //输出结果
108     printf("进行%d次测试,中奖%d次。\n\n", max, z);
109 }

二、C# 测试代码

using System;
using System.Collections.Generic;
using System.Text;

//有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后
//主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门
//现在主持人问你,要不要换个门,请问你换还是不换?
//

namespace Test123
{
    class Program
    {
        //初始化随机数生成器
        static Random random = new Random();

        //入口函数
        static void Main(string[] args)
        {
            //测试总次数
            int count = 20;
            //不换门测试
            Console.WriteLine("不换门测试:");
            test(count, false);
            //换门测试
            Console.WriteLine("换门测试:");
            test(count, true);
        }

        //测试(总次数, 换门)
        static void test(int max, bool change)
        {
            //max    次数:测试的总次数
            //change 换门: 0不换  1换门

            int i;        //循环因子
            int m;        //目标:本次中奖的目标数字
            int c;        //初选:本次选手初次选择的数字
            int x;        //选择:本次选手最终选择的数字
            int p = 0;    //排除:主持人排除掉没奖的数字
            int z = 0;    //中奖:中奖的总次数
            bool b;       //临时布尔类型变量

            //循环多次模拟换门测试
            z = 0; //重置中奖次数
            for (i = 0; i < max; i++)
            {
                m = random.Next(3); //目标:本次中奖的目标数字
                c = random.Next(3); //初选:本次选手初次选择的数字

                //求出主持人要排除的数字
                if (m == c)
                {
                    //选手选择了一个有奖品的,主持人从另外两个没奖品当中随机排除掉一下
                    b = random.Next(2) == 1;  //产生  false or true
                    switch (c)
                    {
                        case 0:  //要排除的是:2 or 1
                            p = b ? 2 : 1;
                            break;
                        case 1:  //要排除的是:2 or 0
                            p = b ? 2 : 0;
                            break;
                        case 2:  //要排除的是:1 or 0
                            p = b ? 1 : 0;
                            break;
                    }
                }
                else
                {
                    //选手选择了一个没奖品的,主持人排除另一个没奖品的
                    //3-(m+c) = p
                    //3-(0+1) = 2
                    //3-(0+2) = 1
                    //3-(1+2) = 0
                    p = 3 - (m + c);
                }

                //决定终选
                if (change)
                {//换门
                    //x=3 - (p + c)
                    //x=3 - (0 + 1) = 2
                    //x=3 - (0 + 2) = 1
                    //x=3 - (1 + 2) = 0
                    x = 3 - (p + c);  //换个门
                }
                else
                {//不换门
                    x = c;  //最终选择和初次选择一样
                }

                //结果
                Console.Write("第{0:00}次  初选的是:{1}, 目标是:{2}, 排除的是:{3}, 终选的是:{4}", i + 1, c, m, p, x);
                if (m == x)
                {
                    //中奖了
                    z++;
                    Console.Write("  (中奖了)\n");
                }
                else
                {
                    //没中奖
                    Console.Write("\n");
                }
            }
            //输出结果
            Console.Write("进行{0}次测试,中奖{1}次。\n\n\n", max, z);
        }


    }
}

三、Java 测试代码

package com.huarui.test;

//有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后
//主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门
//现在主持人问你,要不要换个门,请问你换还是不换?
//
public class Test {
    
    public static void main(String[] args){
        
        //测试的总次数
        int count = 20;
        //不换门测试
        System.out.println("不换门测试:");
        test(count, false);
        //换门测试
        System.out.println("换门测试:");
        test(count, true);
        
    }
    
    //测试(总次数, 换门)
    static void test(int max, boolean change)
    {
        //max    次数:测试的总次数
        //change 换门: 0不换  1换门

        int i;        //循环因子
        int m;        //目标:本次中奖的目标数字
        int c;        //初选:本次选手初次选择的数字
        int x;        //选择:本次选手最终选择的数字
        int p = 0;    //排除:主持人排除掉没奖的数字
        int z = 0;    //中奖:中奖的总次数

        //循环多次模拟换门测试
        z = 0; //重置中奖次数
        for (i = 0; i < max; i++)
        {
            m = (int)(Math.random()*3); //目标:本次中奖的目标数字
            c = (int)(Math.random()*3); //初选:本次选手初次选择的数字

            //求出主持人要排除的数字
            if (m == c)
            {
                //选手选择了一个有奖品的,主持人从另外两个没奖品当中随机排除掉一下
                boolean b =  (int)(Math.random()*2) == 1;  //产生  false or true
                switch (c)
                {
                    case 0:  //要排除的是:2 or 1
                        p = b ? 2 : 1;
                        break;
                    case 1:  //要排除的是:2 or 0
                        p = b ? 2 : 0;
                        break;
                    case 2:  //要排除的是:1 or 0
                        p = b ? 1 : 0;
                        break;
                }
            }
            else
            {
                //选手选择了一个没奖品的,主持人排除另一个没奖品的
                //3-(m+c) = p
                //3-(0+1) = 2
                //3-(0+2) = 1
                //3-(1+2) = 0
                p = 3 - (m + c);
            }

            //决定终选
            if (change)
            {//换门
                //x=3 - (p + c)
                //x=3 - (0 + 1) = 2
                //x=3 - (0 + 2) = 1
                //x=3 - (1 + 2) = 0
                x = 3 - (p + c);  //换个门
            }
            else
            {//不换门
                x = c;  //最终选择和初次选择一样
            }

            //结果
            //, i + 1, c, m, p, x
            
            System.out.format("第%02d次  初选的是:%d, 目标是:%d, 排除的是:%d, 终选的是:%d", i + 1, c, m, p, x);
            if (m == x)
            {
                //中奖了
                z++;
                System.out.print("  (中奖了)\n");
            }
            else
            {
                //没中奖
                System.out.print("\n");
            }
        }
        //输出结果
        System.out.format("进行%d次测试,中奖%d次。\n\n\n", max, z);
    }
}

四、另外,当需要进行1000次测试时,就不适合将每一次测试的结果都进行输出了,代码稍微改一下,将C语言的代码发给大家看看

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//有三扇门,其中一扇门里有奖品,三选一,你选择其中一扇门之后
//主持人先不揭晓答案,而是从另外两扇门中排除掉一个没有奖品的门
//现在主持人问你,要不要换个门,请问你换还是不换?
////测试(总次数, 换门)
void test(int max, int change);

//入口函数
void main()
{
    //各自测试的次数
    int i, count = 1000;

    //初始化随机种子
    srand((unsigned)time(NULL));

    for(i=0;i<5;i++)
    {
        printf("================================\n");

        //不换门测试
        printf("不换门测试:\n");
        test(count, 0);

        //换门测试
        printf("换门测试:\n");
        test(count, 1);
    }
}

//测试(总次数, 换门)
void test(int max, int change)
{

    //max    次数:测试的总次数
    //change 换门: 0不换  1换门

    int i;        //循环因子
    int m;        //目标:本次中奖的目标数字
    int c;        //初选:本次选手初次选择的数字
    int x;        //选择:本次选手最终选择的数字
    int p;        //排除:主持人排除掉没奖的数字
    int z = 0;    //中奖:中奖的总次数

    //循环多次模拟换门测试
    for (i=0; i<max; i++)
    {
        m = rand()%3; //目标:本次中奖的目标数字
        c = rand()%3; //初选:本次选手初次选择的数字
        
        //求出主持人要排除的数字
        if(m==c)
        {
            //选手选择了一个有奖品的,主持人从另外两个没奖品当中随机排除掉一下
            p = rand()%2;  //产生  false or true
            switch(c)
            {
            case 0:  //要排除的是:2 or 1
                p = p?2:1;
                break;
            case 1:  //要排除的是:2 or 0
                p = p?2:0;
                break;
            case 2:  //要排除的是:1 or 0
                p = p?1:0;
                break;;
            }
        }
        else
        {
            //选手选择了一个没奖品的,主持人排除另一个没奖品的
            //3-(m+c) = p
            //3-(0+1) = 2
            //3-(0+2) = 1
            //3-(1+2) = 0
            p = 3-(m+c);            
        }
        
        //决定终选
        if(change)
        {//换门
            //x=3-(p+c)
            //x=3-(0+1) = 2
            //x=3-(0+2) = 1
            //x=3-(1+2) = 0
            x = 3-(p+c);  //换个门
        }
        else
        {//不换门
            x = c;  //最终选择和初次选择一样
        }
        
        //结果
        //printf("第%02d次  初选的是:%d, 目标是:%d, 排除的是:%d, 终选的是:%d", i+1, c, m, p, x);
        if(m==x)
        {
            //中奖了
            z++;
            //printf("  (中奖了)\n");
        }
        else
        {
            //没中奖
            //printf("\n");
        }
    }
    //输出结果
    printf("进行%d次测试,中奖%d次。\n\n", max, z);
}

实践出真理,欢迎大家批评指正。