◇◇新语丝(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)◇◇