专栏名称: 申龙斌的程序人生
分享可繁殖的知识与技能:GTD时间管理、读书心得、个人成长、财富自由之路
目录
相关文章推荐
OSC开源社区  ·  深度实测Manus,我依然认为这就是AI ... ·  2 天前  
程序员的那些事  ·  被骂了!腾讯道歉 + 立刻改正 ·  4 天前  
OSC开源社区  ·  Linux内核往事 ·  3 天前  
程序猿  ·  雷军提出建议!他本人也曾是“受害者” ·  6 天前  
51好读  ›  专栏  ›  申龙斌的程序人生

酒吧美女硬币游戏的程序模拟

申龙斌的程序人生  · 公众号  · 程序员  · 2019-03-17 23:01

正文

这是博弈论里的一个经典问题:

一位陌生美女主动过来和你搭讪,并要求和你一起玩个游戏。美女提议:“让我们各自亮出硬币的一面,或正或反。如果我们都是正面,那么我给你3元,如果我们都是反面,我给你1元,剩下的情况你给我2元就可以了。”

画个表格看一下四种情况的收益,看起来游戏非常公平。

男孩的硬币 美女的硬币 男孩收益
+3
+1
-2
-2



真的公平吗?先不要google,试着自己思考一下。










双方都是随机出硬币


假设两人都是随机给出硬币的正、反面,那么四种情况的概率都是1/4,收益和损失正好相等,赢的概率约等于0。


可以写个C#程序模拟一下这种情况。


先写一个Bet()函数,模拟一次赌局的情况,正面用数字0表示,反面用数字1表示。

// 一次赌局的输赢情况// 返回值为男孩的收益private static int Bet(int boySide, int girlSide){   // 0正面,1反面    if (boySide == 0 && girlSide == 0) return 3;    if (boySide == 1 && girlSide == 1) return 1;    if (boySide == 0 && girlSide == 1) return -2;    if (boySide == 1 && girlSide == 0) return -2;    return 0;}


男孩和女孩都随机出0或1,即正面或反面,模拟赌上1千万次。

private static Random boyRandom = new Random(Guid.NewGuid().GetHashCode());private static Random girlRandom = new Random(Guid.NewGuid().GetHashCode());
private static void BetRandom(){ int boyGain = 0; int gameCount = 10000000; for (int i = 0; i < gameCount; i++) { int boySide = boyRandom.Next(2); int girlSide = girlRandom.Next(2); boyGain += Bet(boySide, girlSide); } Console.WriteLine("男孩的平均收益率: " + (boyGain * 100.0 / gameCount).ToString("0.00") + "%");}


每次运行这个程序的结果并不相同,但男孩的平均收益率大概在 -0.12% 到 0.11%之间。我把上面的函数运行几次的结果见下图。




美女按一定的策略出硬币


假设美女按一定的概率出正面、反面,比如每8次里有3次正面,5次反面,也就是说出正面的概率为3/8。


写个函数BoyRoll()和GirlRoll(),男孩女孩都可以按一定的概率的出硬币。

// 男孩按一定的概率出示硬币的正面// 返回0表示正面,1表示反面private static int BoyRoll(double probFront){    if (boyRandom.NextDouble() < probFront) return 0;    return 1;}// 女孩按一定的概率出示硬币的正面// 返回0表示正面,1表示反面private static int GirlRoll(double probFront){    if (girlRandom.NextDouble() < probFront) return 0;    return 1;}


现在让男孩随机抛硬币,美女按3/8的概率出正面。

int boyGain = 0;int gameCount = 10000000;for (int i = 0; i < gameCount; i++){    int boySide = BoyRoll(0.5);    int girlSide = GirlRoll(3.0 / 8.0);    boyGain += Bet(boySide, girlSide);}Console.WriteLine("男孩的平均收益率: "






请到「今天看啥」查看全文