无意在维基看到了一个关于概率悖论的讨论Boy or Girl paradox。有争议的的题目如下:
  史密斯先生有两个孩子,至少其中之一是男孩,请问两个孩子都是男孩的可能性有多大?
  原文如下:
  Mr. Smith has two children. At least one of them is a boy. What is the probability that both children are boys?
  一部分人的答案是1/3,一部分人的答案是1/2.为什么会产生这样的结果呢,文中说得很清楚是因为问题本身存在歧义,对“至少一个孩子是男孩”的信息做不同的假设,导致了不同的结果。问题归根结底是由于自然语言的二义性,将问题转化成了两个不同的数学模型,从而产生了两个不同的结果。我们知道设计一种编程语言的任务之一就是消除其二义性,因此一般而言编程语言是一种没有歧义的语言(所以程序员都喜欢写代码不喜欢说话么),如果用编程语言来描述这一问题,会不会好理解点呢?以java为例,我们来看看。
  以下是对史密斯先生有两个孩子的可能情况进行描述,其中random.nextBoolean()函数随机返回true或false的概率均为1/2,用于模拟现实中生男孩女孩的概率各一半。可见程序不仅描述了所有的组合,还明确了题目中暗含的条件。

 class TwoChildren{Child child1;Child child2;public TwoChildren()//一个孩子是男孩或女孩的概率是50%{child1 = random.nextBoolean()?Child.BOY:Child.GIRL;child2 = random.nextBoolean()?Child.BOY:Child.GIRL;}}

  接着描述“至少一个孩子是男孩”,因为这里是存在歧义的地方,所以转化成代码描述时,我们会根据两个不同的假定,得到不同的代码。1/3结果的假定条件:观察了史密斯的两个孩子,其中一个是男孩:

boolean isObserved(TwoChildren draw)
{return draw.child1 == Child.BOY || draw.child2 == Child.BOY;
}

熟悉java的程序员会注意到,如果child1为BOY的话,child2不会被观察(||运算符后面的代码不会被执行),是否和自然语言描述不一样?我们从逻辑或运算定义可知二者是等价的,即使||运算符后面的代码被执行,也不影响程序结果,换成自然语言就是我们观察史密斯的两个孩子时,一个一个的观察,如果发现其中一个是男孩,就已经保证了“至少一个是男孩”,就没必要接着观察了。
  接着描述1/2的结果假定条件:随机观察了史密斯的一个孩子,其中一个是男孩:

boolean isObserved(TwoChildren draw)
{return random.nextBoolean()?draw.child1 == Child.BOY:draw.child2 == Child.BOY;
}

其中random.nextBoolean()函数随机返回true或false的概率均为1/2,就是两个孩子被选中观察的概率是1/2.

最后我们描述问题的提出

if(isObserved(draw))
{observedCount ++;if(draw.child1 == Child.BOY && draw.child2 == Child.BOY){//两个孩子都是男孩matchedCount++;//经过很多次运算后,((double)matchedCount/observedCount)最可能的值是多少?}
}

  至此我们将一个以自然语言描述的问题,转化成了一个以程序语言描述的问题。这个转化是否正确呢,我们做10万次测试,看结果是否满足数学推导的预期。以下是一个完整的测试代码:

package hermitdl.test2;import java.util.Random;/*** Test for <<Boy or Girl paradox>>*/
public class App
{static enum Child{BOY,GIRL};static Random random = new Random();static class TwoChildren{Child child1;Child child2;public TwoChildren()//一个孩子是男孩或女孩的概率是50%{child1 = random.nextBoolean()?Child.BOY:Child.GIRL;child2 = random.nextBoolean()?Child.BOY:Child.GIRL;}}//随机检查一个孩子的性别是否是男孩static class PeekOneTest extends ProbabilityTest{@Overrideboolean isObserved(TwoChildren draw) {return random.nextBoolean()?draw.child1 == Child.BOY:draw.child2 == Child.BOY;}}//检查两个孩子的性别,是否其中之一是男孩static class PeekTwoTest extends ProbabilityTest{@Overrideboolean isObserved(TwoChildren draw) {return draw.child1 == Child.BOY || draw.child2 == Child.BOY;}}static abstract class ProbabilityTest{int observedCount = 0;int matchedCount = 0;//在isObserved为真的情况下计数,以及两个孩子均是女孩的情况计数。void test(TwoChildren draw){if(isObserved(draw)){observedCount ++;if(draw.child1 == Child.BOY && draw.child2 == Child.BOY){两个孩子都是男孩matchedCount++;}}}abstract boolean isObserved(TwoChildren draw);void printResult(){System.out.printf(this.getClass().getSimpleName() +"=%d/%d=%f\n",matchedCount,observedCount,((double)matchedCount/observedCount));}}public static void main( String[] args ){PeekOneTest peekOneTest = new PeekOneTest();PeekTwoTest peekTwoTest = new PeekTwoTest();TwoChildren draw;for(int i = 0;i < 1000000; i++){draw = new TwoChildren();peekOneTest.test(draw);peekTwoTest.test(draw);}peekOneTest.printResult();peekTwoTest.printResult();}
}

以下为程序的几次运行结果:
PeekOneTest=249436/499301=0.499570
PeekTwoTest=249436/750234=0.332478

PeekOneTest=250209/500229=0.500189
PeekTwoTest=250209/749846=0.333681

PeekOneTest=249963/500234=0.499692
PeekTwoTest=249963/749712=0.333412

  可见模拟结果始终分别在1/2与1/3附近波动,是符合数学预期的。

用程序消除一道概率题的二义性相关推荐

  1. 一道概率题引发对考研数学复习的思考

    一道概率题引发对考研数学复习的思考 知识回顾 如题,今天上午我兴致勃勃地拿出2006年数学一做了起来.做前面还算顺利,直到最后那道概率题,关于极大似然估计的题目,我的内心:艹了,这怎么跟之前做的不一样 ...

  2. 使用程序解决一道逻辑推理题

    今天看朋友发了一个老问题,一道很有意思的推理题:(转载请指明出于breaksoftware的csdn博客) 小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日是下列10组中的一 ...

  3. 一道概率题:重男轻女的情况下家庭女孩数量的问题

    2014.3.29阿里巴巴实习生招聘笔试题上出了这样一道选择题: 某国家非常重男轻女,一个家庭如果生了一个女孩,便要再生一个,直到生下男孩为止,假设生男生女概率一样,则平均每户人家有几个女孩? 显然这 ...

  4. 时间流逝(flow)——概率题

    时间流逝(flow) Time Limits: 1s Memory Limits: 256MB Description 生活可以很简单.可以探索水底世界的神秘,也可以去发现奇特新生物,亦或踏上一段新生 ...

  5. (组合数学习题)递推关系一道经典题分析与解答

    文章目录 题目 分析与解答 求解 程序实现(C++) 题目 来看下面一道题,主要用到的是组合数学中的递推关系部分的内容. 某长度为nnn的二进制序列,要求其中至少有连续的333个000出现,问:能产生 ...

  6. 计算机软件水平考试分类程序员,历年计算机软件水平考试程序员部分真题

    试题1 A.为了提高计算机的处理机和外部投备的利用率, 把多个程序同时放入主存储崐器,在宏观上并行运行. B.把一个程序划分成若干个可同时执行的程序模块的设计方法. C.多个用户在中端设备上以交互方式 ...

  7. 基于2022高考数学全国卷I概率题解题思路初步分析新冠病毒疫苗

    基于2022高考数学全国卷I概率题解题思路初步分析新冠病毒疫苗 1. 2022高考数学全国卷I概率题 2. 卡方(χ2\chi^2χ2)检验原理回顾 3. 解答2022高考数学全国卷I概率题 4. 上 ...

  8. 2009年9月刊《程序员》算法题之我见——思索之一

    本系列文章目录 2009年9月刊<程序员>算法题之我见--思索之一 2009年9月刊<程序员>算法题之我见--思索之二 2009年9月刊<程序员>算法题之我见--思 ...

  9. 程序员考试下午题知识点总结

    程序员考试下午题知识点总结 第一大题:程序框图 程序流程图又称程序框图,是用统一规定的标准符号描述程序运行具体步骤的图形表示.程序框图的设计是在处理流程图的基础上,通过对输入输出数据和处理过程的详细分 ...

最新文章

  1. java反射 获取参数名_java
  2. AngularJS---核心特性
  3. html textarea换行和dom换行
  4. python基础入门: for 循环
  5. Https 加密原理分析
  6. arcgis导出access数据库能打开的文件
  7. .net面试题(会持续更新)
  8. C++中的Overload、Override和Overwrite
  9. 算法:平衡二叉树110. Balanced Binary Tree
  10. 《Bible》各版本
  11. 小型矢量图标于前端页面如何应用
  12. 黑金AX7Z100 FPGA开发板移植LWIP库(二)PL端
  13. ubuntu下CHM阅读器
  14. Jwt入门教程:实战( 三) | 使用Springboot基于拦截器和redis的Jwt判断用户登录以及安全校验
  15. android网易云播放时图片,Android 网易云音乐图片高斯模糊
  16. native react 图片多选_N-第三方-react-native-image-picker,选择图片上传
  17. 百度终于要出手了?文心一言
  18. 苹果不创新,库克有道理
  19. sqoop导入数据到hive
  20. 如何锁定 input 内容不可修改

热门文章

  1. python个人博客搭建说明书_技术分享|利用Python Django一步步搭建个人博客(二)...
  2. 刘知远、赵鑫、施柏鑫:AI青年科研人员成长之路
  3. SAP PM 初级系列1 – 定义维护工厂和维护计划工厂
  4. SAP SD基础知识之组织架构设计-Shipping Point篇
  5. SAP SD基础知识之交货单不完全日志
  6. 正则化方法:L1和L2 regularization、数据集扩增、dropout
  7. 「机器学习速成」训练神经网络:反向传播、梯度爆炸消失Dropout
  8. 法国科学家发布AI模型,阐释蛋白结构和功能及进化关系
  9. 监督学习和无监督学习
  10. 前沿丨人工智能的框架战争:FB继续挑战Google