◇◇新语丝(www.xys.org)(xys3.dxiong.com)(www.xysforum.org)(xys2.dropin.org)◇◇

  滚屏抽号与“海量”的关系

  作者:zeroyear

  如何保证电脑程序的可信性,保证程序不被做手脚,这个问题当年小布什和
戈尔在电子计票问题上就较量过。美国总统选举尚且如此,央视的滚屏抽号自然
也难以信赖,这应该是共识。但是,奥卡姆剃刀网友在技术和理论方面谈到随机
和等概问题时,强调了“海量”这个特点,我觉得“海量”无须强调,我有两点
看法:

  第一,手机号不过只有十一位数字(而且第一位总是1,实质上就只有十
位),粗枝大叶地计算,用八个字节存储每一个号码,再用四个字节存储对应的
每一个编号,这样一来,一千万条记录,总共最多需要十二千万字节,也就是一
百二十兆字节(120MB),这远远算不上“海量”。只相当于说,通过短信平台
把号码采集起来之后,按当前的普通配置,全部数据用家用电脑内存容量(2GB)
的十分之一来装载就绰绰有余了。

  第二,哪怕只有区区十个编号,要做到被选的完美等概恐怕也不容易,无非
是编号少的情况下,等概性更容易“验证”罢了。当然,更容易“验证”也就意
味着更容易设计算法来测试。但是如果十个编号的等概效果已经有现成的算法勉
强实现了,那么直觉上,一千万个编号的等概效果没有理由达不到,因为总有办
法组合出来。由于一千万现在真的算不上“海量”,用家用电脑就可以粗略体验
一下滚屏抽号的等概效果。

  唾手可得的C语言的运行时库中就有rand函数,这个函数用于生成“均匀地”
介于0与32767之间(闭区间)的随机整数。对此区间进行缩放,即可获得介于0
与任何小于32767的数之间的数。比如,rand()*399/32767的值将介于0与399之
间。不失一般性,不妨设置两个种子来初始化两个独立的随机数生成器,第一个
生成介于0与32767之间的数N1,第二个生成介于0与399之间的数N2,那么
N1*400+N2就是介于0与13107199(千万数量级)之间的数。一个数或者说一个编
号被生成,就相当于一个手机号被选中,现在不妨生成13107200×1000(千亿数
量级)个编号,看看一千三百多万个手机号的每一个被选中的次数是否接近。

  理想情况下,每一个将被选中1000次。按普通家用电脑配置,每一次试验最
多需要一小时,这绝不是什么天文数字。rand函数对种子初始化是敏感的,但这
主要体现在刚开始运行的时间,最多不超过数秒。我用手头的硬件资源进行了五
十次试验,观察到的结果是比较稳定的。比如,其中一次的结果是,编号
6038537被选中890次,编号427334被选中1105次,前者是这次试验中被选中次数
最少的,后者则最多。两者离完美的1000次均有一定差距,但只要先把一千三百
万多个编号与手机号随机关联,哪个手机号被选中的概率最大也就根本无法预料,
公众应该可以接受这样的随机和等概效果。做为对比,用rand函数瞬间生成
10000个只介于0与10之间的数,效果也不过就是如此了,这一定程度上表明“海
量”不影响同一个算法的等概效果。当然,rand函数只针对32768个数字,为
“海量”而设计的一步到位的更好的算法一定能达到更好的效果,但rand函数至
少可以让人觉得哪怕是用简单现成的算法,“海量”滚屏抽号的等概性也是可以
接受的。

  程序虽然容易被做手脚,但是程序的优点却很难替代,尤其面对“海量”问
题时,电脑选号恰恰是最能够被“验证”是基本公平的,几乎也是唯一的。一千
万个号码如果用乒乓球摇奖的话,其等概性根本不可能被“验证”,而只能从理
论上相信之,因为全世界的乒乓球摇奖次数加起来都未必超过一千万次,无法靠
现成的数据统计。如果要做“验证”的话,就算每秒钟能摇奖一次,只摇一千三
百万多次来观察(期待每个号被选中一次),也需要一刻不歇地摇上大半年了。

(XYS20090221)

◇◇新语丝(www.xys.org)(xys3.dxiong.com)(www.xysforum.org)(xys2.dropin.org)◇◇