空间上统治宇宙的是万有引力(远远超过电磁力、强力和弱力),时间上统治宇宙的则是大数定理。
引子
这两天为了测试定时刷新功能,编写了一小段代码,每秒产生一个随机数,如果随机数大于0.999,就弹出通知框,模拟定时刷新数据库查看偶发事件的程序。
没想到,这段代码似乎很爱表现,本来按理说每小时应该产生3.6个,但实际上经常刚运行1分钟就弹出来了,还经常连续跳。
这咋回事呢?难道程序中潜伏着一个智慧生物?
于是修改了代码,昨天测试了一晚上,结果如下:
Mon Feb 20 22:08:39 UTC+0800 2012: start!
Mon Feb 20 22:15:28 UTC+0800 2012:0.9996775767156192
Mon Feb 20 22:26:45 UTC+0800 2012:0.9993164486570707
Mon Feb 20 22:39:41 UTC+0800 2012:0.9991614030679405
Mon Feb 20 22:52:17 UTC+0800 2012:0.9993802612934692
Mon Feb 20 22:57:18 UTC+0800 2012:0.9992101100747147
Mon Feb 20 23:49:47 UTC+0800 2012:0.9994722976553704
Tue Feb 21 00:32:22 UTC+0800 2012:0.9993711621307835
Tue Feb 21 00:44:49 UTC+0800 2012:0.9997594440820359
Tue Feb 21 00:59:11 UTC+0800 2012:0.9990013300168501
Tue Feb 21 01:01:05 UTC+0800 2012:0.9995229600977049
Tue Feb 21 01:06:59 UTC+0800 2012:0.999817806874123
Tue Feb 21 01:43:27 UTC+0800 2012:0.9991565107679405
Tue Feb 21 01:52:45 UTC+0800 2012:0.9994827659434577
Tue Feb 21 01:56:38 UTC+0800 2012:0.9994192574575108
Tue Feb 21 02:01:23 UTC+0800 2012:0.9992681562004064
Tue Feb 21 03:19:18 UTC+0800 2012:0.9996777448874157
Tue Feb 21 03:22:19 UTC+0800 2012:0.9996629119550424
Tue Feb 21 03:24:53 UTC+0800 2012:0.9992419533798492
Tue Feb 21 03:28:41 UTC+0800 2012:0.999059605995319
Tue Feb 21 03:32:00 UTC+0800 2012:0.9990270301026873
Tue Feb 21 04:12:00 UTC+0800 2012:0.9993799632901426
Tue Feb 21 04:17:32 UTC+0800 2012:0.9994741351743861
Tue Feb 21 04:26:54 UTC+0800 2012:0.9993270924804556
Tue Feb 21 04:30:12 UTC+0800 2012:0.9994040516631909
Tue Feb 21 04:52:36 UTC+0800 2012:0.9995258410445615
Tue Feb 21 05:39:31 UTC+0800 2012:0.999388751953785
Tue Feb 21 05:43:27 UTC+0800 2012:0.9999265437402556
Tue Feb 21 05:50:03 UTC+0800 2012:0.9997207089599427
Tue Feb 21 05:56:21 UTC+0800 2012:0.9998498736376766
Tue Feb 21 06:16:08 UTC+0800 2012:0.9999746575172905
Tue Feb 21 06:23:04 UTC+0800 2012:0.9997999256014357
Tue Feb 21 06:57:41 UTC+0800 2012:0.999702550543468
Tue Feb 21 07:29:17 UTC+0800 2012:0.9996094465673534
Tue Feb 21 07:29:53 UTC+0800 2012:0.9992936536360875
Tue Feb 21 07:31:19 UTC+0800 2012:0.9994029914395262
Tue Feb 21 07:33:24 UTC+0800 2012:0.9999636418665332
Tue Feb 21 07:45:48 UTC+0800 2012:0.9990307948678938
现在时间是08:40(有接近一小时没弹出来啦!)
在10.5小时时间里,弹出了37个,几乎完全等于3.6个/小时。如果观察局部,在最后7:29~7:33连续弹出了4个,而在最后的一小时,则一个没弹。
但局部的偶然事件并不会影响大量统计的结果,这就叫大数定理,就是当数目多到一定程度后,统计规律将占据统治地位,结果将趋向于事件的数学期望。
一些偶发的连续弹出,在心理上造成了“爱表现的智慧生物”的错觉。
代码如下有空可以玩玩:
用途
这东西有什么用?在http://blog.csdn.net/cheny_com/article/details/7001982中提到过,当年牛顿时代磨制望远镜,就是利用了大数定理,用纯手工把镜面精度加工到1/8光波长。
在软件估算中,大数定理也非常有用。如果同样一个项目,如果分成10个大块来分别估算,就不如分成20个来得准确。尽管事后会发现无论10个还是20个,每个任务都一样估不准,但是把20个任务加在一起,剩余误差比10个的时候要小很多。
这就是为什么要做WBS分解,然后估算任务的原因。对于敏捷开发的估算,如果能把大型的(超过5人天的)任务分解一下,再行估算,然后相加,误差会小很多。
但是为什么呢?有什么数学原理在起作用?
这就要讲到随时变量相加时的“卷积”运算。
比如抛硬币,抛1次,正反的概率分别0.5,抛两次,则不会说两正两反的概率分别0.5,而是中间插进来个一正一反,而且还占据了大头,成为0.25-0.5-0.25的格局。
如果用整数表示,可以看到下面的三角形:
01次:1 1
02次:1 2 1
03次:1 3 3 1
04次:1 4 6 4 1
05次:1 5 10 10 5 1
06次:1 6 15 20 15 6 1
07次:1 7 21 35 35 21 7 1
...
01次时的11意思是说1正+1反
02次时的121意思是说1/4个两正+2/4个1正1反+1/4个两反,4是所有数字之和
03次的1331=1/8个3正+3/8个2正1反+3/8个1正2反+1/8个三反,8是所有数字之和
……这个三角形叫做杨辉三角形,还是中国人发明的,可以参考最后的链接。
随着次数的增多,极端情况越来越少,而中央鼓起来一个大包。如果连续抛7次硬币,你可以只押4正3反或3正4反,就能有70/128的胜率。
随机变量在相加时,中间鼓起来的现象叫做“卷积”。(额……只能先这么说了)
下面这些事情都和大数定理相关:
1. 分得细估得准(永远不要追求单个任务估算得很准,硬币怎么抛,都是一正一反,多抛几次就得了)
2. 用的多缺陷少(所以要赶紧作出可运行软件跑着)
3. 看的多缺陷少(所以要代码审查)
4. ……等等
杨辉三角型:http://baike.baidu.com/view/298289.htm
大数定理的百度词条不对。