#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
// 一个源自博弈论的数学游戏问题:
// 参赛者会看见三扇门,
// 其中一扇门的里面有一辆汽车,
// 选中里面是汽车的那扇门,
// 就可以赢得该辆汽车,
// 另外两扇门里面则都是一只山羊。
// 当参赛者选定了一扇门,
// 主持人会开启另一扇是山羊的门;
// 并问:“要不要换一扇门?”
// 依照玛丽莲·沃斯·莎凡特的见解,参赛者应该换,
// 换门的话,赢得汽车的概率是2/3。
// 这问题亦被叫做蒙提霍尔悖论:
// 因为该问题的答案虽在逻辑上并无矛盾,
// 但十分违反直觉。
// 验证3门定理
// 1. 先验证不换门的情况
// 2. 再验证换门的情况
// 验证具体设计思路
// 1. 先创建一个10万次的循环实验;
// 2. 每个试验都有一个三个元素的数组;
// 3. 数组分别是两个0一个1;
// 4. 先随机交换3次数组;
// 5. 再随机选一个数组中的元素;
// 6. 此时,再分别检查另外两个数组,公布其中一个元素是0的数组;
// 7. 最后记录选中1的次数;
//
void Swap(int *a, int *b)
{
int iTmp = *a;
*a = *b;
*b = iTmp;
}
bool GuessWithNoSwitch(void)
{
// 1. 创建一个三个元素的数组
static int arrInt[3] = { 0, 0, 1 };
// 2. 先随机交换三个数组中元素的位置
for (int iIdx = 0; iIdx < 3; ++iIdx)
{
// 2.2 获取两个随机数(0~2的范围内)
const int iRandom1 = rand() % 3;
const int iRandom2 = rand() % 3;
// 2.3 交换两个数组元素
Swap(&arrInt[iRandom1], &arrInt[iRandom2]);
}
// 3. 随机选中一个数组元素
const int iRandom3 = rand() % 3;
if (0 == arrInt[(iRandom3 + 1) % 3])
{
// 3.1 公布此数组元素是0
}
else if (0 == arrInt[(iRandom3 + 2) % 3])
{
// 3.2 或者公布此数组元素是0
}
// 4. 检查是否选中1
bool bCheck = false;
if (1 == arrInt[iRandom3])
{
bCheck = true;
}
return bCheck;
}
bool GuessWithSwitch(void)
{
// 1. 创建一个三个元素的数组
static int arrInt[3] = { 0, 0, 1 };
// 2. 先随机交换三个数组中元素的位置
for (int iIdx = 0; iIdx < 3; ++iIdx)
{
// 2.2 获取两个随机数(0~2的范围内)
const int iRandom1 = rand() % 3;
const int iRandom2 = rand() % 3;
// 2.3 交换两个数组元素
Swap(&arrInt[iRandom1], &arrInt[iRandom2]);
}
// 3. 随机选中一个数组元素
int iRandom3 = rand() % 3;
if (0 == arrInt[(iRandom3 + 1) % 3])
{
// 3.1 公布此数组元素是0,并且切换选中的元素为下面的((iRandom3 + 2) % 3)
iRandom3 = (iRandom3 + 2) % 3;
}
else if (0 == arrInt[(iRandom3 + 2) % 3])
{
// 3.2 或者公布此数组元素是0,并且切换选中的元素为上面的((iRandom3 + 1) % 3)
iRandom3 = (iRandom3 + 1) % 3;
}
// 4. 检查是否选中1
bool bCheck = false;
if (1 == arrInt[iRandom3])
{
bCheck = true;
}
return bCheck;
}
int main(int argc, char* argv[])
{
// 1. 先设置伪随机数的种子
srand((unsigned int)time(NULL));
// 2. 打印交互语句
printf("The first case: No witch choice!\n");
// 3. 先设置最大选择次数(当前是十万次)
const int iMaxCount = (int)1e5;
// 4. 用于记录当前选中“数字1”的次数
int iCntNoSwitch = 0;
for (int iIdx = 0; iIdx < iMaxCount; ++iIdx)
{
if (GuessWithNoSwitch())
{
++iCntNoSwitch;
}
}
// 5. 计算第一种方式选中的“频率”
const double dRatio1 = 1.0 * iCntNoSwitch / iMaxCount;
printf("case 1 ratio: %lf\n", dRatio1);
// 6. 打印交互语句
printf("The second case: Witch choice!\n");
// 7. 用于记录当前选中“数字1”的次数
int iCntSwitch = 0;
for (int iIdx = 0; iIdx < iMaxCount; ++iIdx)
{
if (GuessWithSwitch())
{
++iCntSwitch;
}
}
// 8. 计算第二种方式选中的“频率”
const double dRatio2 = 1.0 * iCntSwitch / iMaxCount;
printf("case 1 ratio: %lf\n", dRatio2);
return 0;
}
用C语言验证“三门定理”
最新推荐文章于 2024-08-15 10:12:07 发布