不那么随机的随机数列
曾经看过这样一种赌徒的策略:假设在一场赌大小的赌博游戏中,赔率是 1:1 ,而庄家不会出千,开大和开小的概率均等(皆为 50%)。赌徒一开始压一块钱,如果他压错了,那么下一次就压两块,再错继续加倍。一旦压对,赌徒永远可以保证有一块钱的进帐。并且从 1 块钱重新开始。
看起来,这种策略能保证永远包赚不赔。但实际上为什么没有人用这个方案发财呢?
放到现实中,试图采用这个策略去赌博的人,几乎都会赔的倾家荡产(当然只要是赌博,差不多都是这个结局)。不要怪运气,不要怪庄家出千,因为这个策略从一开始就注定了失败。
让我们把赌博游戏换成等价的扔硬币实验。请问,连续掷出 7 次正面的概率有多少?
稍有概率常识的人都可以心算出答案:1/128 ,也就是略小于 1% 。比 D&D 跑团时投出 20 重击要难多了(拜一下骰子大神)。
那么,谁能凭直觉说出,掷 30 次硬币,至少出现一次“连续 7 次正面”的概率有多少?我写了个小程序计算了一下,答案远大于大多数人的直觉,居然达到了 18.3% 这么高。
好了,现在把掷出正面换成压对大小。也就是说,你参加 30 次赌局,出现连续 7 次压对,或连续 7 次压错的概率并不那么的小。而且这个概率还会随着赌局次数增加,逐渐趋近于 1 。
这意味着什么?
如果你只有 128 块的赌本,在 30 次赌局中,输光的可能性居然有 9.53% 这么高。诚然,你可以运气很好,在一开始赢到一些额外的资金。但促进最初的策略所需要的进一步资金是 256 块,在 30 次赌局中是绝对不可能办到的。
赌徒可以增加自己的赌本,让自己可以承受更多的连续失败。但赌本的增加将是指数级上升的,但对提高不至于输光的概率却很有限(线形增加)。只要他在赌场上玩上一通宵,多少钱都能输干净。
赌博最终就是看谁的本钱多,而不是谁的运气更好(骰子大神啊,请不要跟我绝交。谈谈数学而已,莫要当真)。如果你赌本比不过庄家,乘早收手吧。btw, 这话是写给众多转战 A 股的朋友们的。
我想任何一个具有理性思维的人都不会对赌博有太多兴趣。想必我的 blog 的读者中这样的人居多,其实我今天主要是想谈游戏的 :) 。
我们前段开始内测了一个卡牌游戏 (注:需要内测帐号的朋友请自己去官方论坛 申请,不要找我 :) )
在测试时,同事在50 张的卡组里放了 25 张生物卡。并认为,在游戏中每次摸新的卡,是生物卡的概率是 50% 。可是在实际游戏中,几乎每局都会发生连续 5 次都摸不到生物卡的情况。
一开始,我们认为系统的伪随机函数生成的伪随机数列不够随机。后来换了一个随机数函数,情况并没有得到改善。
今天我计算了一下,如果是掷硬币实验,连续 30 次中,至少出现 5 次连续正面的概率达到了 36.82% 。当次数增加到 44 次后,概率超过了一半,达到了 50.32% 。而我们的卡牌游戏,几乎每局都会有 30 多次摸牌机会,出现连续 5 次摸不到生物卡的概率其实够大了。经常出现这种情况,还真是怪不了伪随机数列的生成算法,或是洗牌函数。
写到这里,还有人不信邪。我掏出了我的 20 面骰 。在桌上做起实验。
我们规定,投出 1-10 算小,11-20 算大。一直投下去,直到出现 5 次连续的大、而后游戏结束。最后统计一共投了多少次。在没有进行游戏之前,有人估计可能每玩一局可能会投接近 100 次;可实际结果另他失望(更接近计算结果)。
我们一共做了三组实验,分别在 22 次,24 次,31 次结束了。
如果有朋友想试试,可以用硬币或麻将用的六面骰实验。
所以说,当你在打网络游戏时,如果某天发现某件装备的凋落率,或是合成率远低于官方公布的数字。请不要抱怨自己命不好,也不要怀疑系统作弊。若让程序员们产生一个特定分布的作弊随机数列,又不那么容易被人看出规律(不够随机)出来,难度和成本(CPU 成本)比采用系统的随机数发生器要大的多。比如使用 Niederreiter Sequence 。
最后附一张图片,我随手用一个 C 程序生成的。程序在图片的下方:
用任何 C 编译器编译运行,再用管道输出到一个 .pbm 图片文件中即可。它生成了 2000 个伪随机数,并作为 1000 个点画在画布上。
我们可以发现,很多点都碰在了一起(一致随机分布往往呈现出的这种集束现象)。这并非随机数产生的不好,而是一种常态而已。
反过来,开发人员真的想讨好玩家,可以做一个更“均匀”的随机数列。让游戏中的各种概率发生更符合“大众的直觉”。那么,考虑使用 准随机数列 (quasi-random_sequences)。不过要注意,计算量会增加很多。而且这样的数列并不随机,只是讨好玩家而已,跟物理世界中的随机性相差甚远。
在《科学计算导论》的中译版中,把 quasi-random sequences 也翻译作拟随机数列。这里有一篇介绍性质的 paper 可以参考。
9 月 11 日补充:
原稿中概率计算有误,今天修正过来。感谢纠正它们的朋友。附上我的递推公式:
如计算 N+1 次实验中连续 5 次正面的概率,可先计算 N+1 次的投掷实验所有可能出现的组合数为 2 ^ (N+1) ,再计算其中出现连续 5 次正面的次数 f(N+1)。
f(N+1) 可以递推得到:
f(N+1) = f(N)*2 + 2 ^ (N-5) - f(N-5)
其中 当 N==5 时,f(N)=1 ;当 N<5 时,f(N)=0
f(N)*2 指前 N 次中已经掷出 5 次正面的组合数,无论最后一次结果如何都计算在内。
2^(N-5) - f(N-5) 指前 N 次的最后 4 次掷出了 4 次正面,而从未掷出连续 5 次正面的组合数,此时只需要最后一次也掷出正面即可。
Comments
Posted by: 惠盈盈 | (53) November 22, 2021 02:03 PM
Posted by: 杨博 | (52) March 9, 2018 04:45 PM
Posted by: 杜 | (51) March 8, 2017 11:04 AM
Posted by: xp | (50) February 18, 2014 05:26 PM
Posted by: kevin | (49) August 14, 2012 03:10 PM
Posted by: nothanks | (48) December 2, 2010 04:25 PM
Posted by: Cloud | (47) December 1, 2010 12:17 PM
Posted by: 依然是我 | (46) December 1, 2010 01:52 AM
Posted by: Anonymous | (45) December 1, 2010 01:36 AM
Posted by: Anonymous | (44) December 1, 2010 01:22 AM
Posted by: Tone | (43) March 24, 2010 01:27 AM
Posted by: Cloud | (42) January 19, 2009 04:22 PM
Posted by: fonix | (41) January 19, 2009 03:17 PM
Posted by: Cloud | (40) September 11, 2008 01:29 PM
Posted by: peter | (39) September 11, 2008 10:03 AM
Posted by: peter | (38) September 10, 2008 09:04 PM
Posted by: peter | (37) September 10, 2008 08:58 PM
Posted by: santiago | (36) August 28, 2008 04:27 PM
Posted by: barrywu | (35) August 26, 2008 06:06 PM
Posted by: santiago | (34) August 26, 2008 03:01 PM
Posted by: barrywu | (33) August 26, 2008 09:51 AM
Posted by: flyff | (32) May 5, 2008 09:29 AM
Posted by: cowind | (31) April 30, 2008 11:23 AM
Posted by: 袭 | (30) April 26, 2008 10:06 AM
Posted by: ot512 | (29) April 25, 2008 09:00 PM
Posted by: Spe | (28) April 24, 2008 02:20 PM
Posted by: Cloud | (27) April 24, 2008 12:11 PM
Posted by: boyi | (26) April 24, 2008 11:33 AM
Posted by: buffer | (25) April 24, 2008 09:30 AM
Posted by: Felix Wong | (24) April 24, 2008 01:12 AM
Posted by: ablmf | (23) April 23, 2008 10:15 PM
Posted by: yafare | (22) April 23, 2008 10:13 PM
Posted by: Felix Wong | (21) April 23, 2008 02:00 PM
Posted by: dayn9 | (20) April 23, 2008 01:08 PM
Posted by: Cloud | (19) April 23, 2008 11:33 AM
Posted by: rotApple | (18) April 23, 2008 11:17 AM
Posted by: Felix Wong | (17) April 23, 2008 08:59 AM
Posted by: nothanks | (16) April 22, 2008 10:25 PM
Posted by: Cloud | (15) April 22, 2008 10:20 PM
Posted by: adon | (14) April 22, 2008 09:33 PM
Posted by: liuworld | (13) April 22, 2008 05:41 PM
Posted by: Spe | (12) April 22, 2008 03:26 PM
Posted by: Jean | (11) April 22, 2008 11:49 AM
Posted by: nothanks | (10) April 22, 2008 10:43 AM
Posted by: nothanks | (9) April 22, 2008 10:40 AM
Posted by: 不空 | (8) April 22, 2008 12:49 AM
Posted by: 不空 | (7) April 22, 2008 12:46 AM
Posted by: Anonymous | (6) April 21, 2008 11:33 PM
Posted by: Cloud | (5) April 21, 2008 11:21 PM
Posted by: justseesee | (4) April 21, 2008 11:00 PM
Posted by: rainfiel | (3) April 21, 2008 10:46 PM
Posted by: Cloud | (2) April 21, 2008 10:01 PM
Posted by: Felix Wong | (1) April 21, 2008 09:41 PM