标签:可能性 自然语言 假设 getc 编程语言 next 存在 结果 https
无意在维基看到了一个关于概率悖论的讨论Boy or Girl paradox。有争议的的题目如下: 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
{
@Override
boolean isObserved(TwoChildren draw)
{
return random.nextBoolean()?draw.child1 == Child.BOY:draw.child2 == Child.BOY;
}
}
//检查两个孩子的性别,是否其中之一是男孩
static class PeekTwoTest extends ProbabilityTest
{
@Override
boolean 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附近波动,是符合数学预期的。
标签:可能性 自然语言 假设 getc 编程语言 next 存在 结果 https
原文地址:http://blog.51cto.com/13981273/2315533