刷微博的时候看到一家互联网公司组织年会,在抽奖的环节中,一群程序员觉得这个抽奖程序有猫腻,纷纷提出质疑,于是 CTO 就带头把程序代码显示出来,一个年会变成了一场代码 Review 会 。。
每个公司的年会应该都会有抽奖环节吧,如果说图省事儿直接让公司员工写一个抽奖程序,也是可以的。如果过的再精致点儿,可能会选用更有权威的第三方抽奖程序。我就为公司写过三次抽奖程序,随着公司的发展,每年的要求都不一样,(虽然现在已经改为互动性更强的微信抽奖啦).所以我的代码逻辑一直在做变更。最新一版的源码我已经开放在了 Github 上,由于是一两年前的代码,使用的框架还是 ThinkPHP,不过换汤不换药,具体的随机生成逻辑还是一样的。无非是使用或函数从一个范围选取一个随机数,然后匹配到对应这个随机数的幸运儿。代码看起来是这样:
// 获取未中奖的人数
$max=count($list)-1;
// 将所有人排为一个列表 然后取这个列表的随机值
$seed=$max>?mt_rand(,$max):;
// 此时 name 就是中奖的这个人了
$name=$list[$seed]['name'];
# 后续操作...
那么问题来了,我所处的环境也是一个大型互联网公司,虽然我这个抽奖程序是凭良心纯随机生成的随机数,但是那天也发生了中奖的人大多都在财务部门,技术部的人一个都没有的狗血结果…所以那次抽奖后就会有很多技术小伙伴提出质疑:是不是有后门!财务部是不是请你吃饭了!…虽然只是开玩笑的说一下,后来我想了想,可能还真的有点猫腻...
从程序角度来讲,任何语言生成的随机数其实都是伪随机,说白了它也是通过固定的算法产生的数据,所以不是很能让人信服。甚至还可以总结出规律预测出结果!至于我写的程序中每次使用的随机数都是使用程序内置函数生成,所以出现那天分配不均的情况也不是不可能。那么,我们要如何生成一个真正的随机数呢?大家想一下,彩票的中奖号码是通过人为干预随机产生的,投骰子也是纯随机的… 那么我们是不是也可以利用大自然的任何元素来作为随机种子的生成器呢?哈哈,答案是可以的,有一个国外的机构(https://www.random.org),Random.org 通过大气噪音 (Atmospheric Noise) 生成真随机数,由爱尔兰都柏林三一学院 Mads Haahr 博士于 1998年 创建。在他们的官网上,有一个很形象的例子:
有两张分辨率为 512*512 的图是通过他们的大气噪音和 PHP 的函数生成的点阵图。很明显,通过大气噪音生成的颗粒度很均匀,几乎看不出来有任何的规律。而 PHP 利用伪随机生成的图片就可以清楚的看到类似于栅栏的趋势。这就说明,他们的产品真正做到了“真随机”。所以我们可以借助他们提供的免费 API,就能彻彻底底的生成一个范围内的随机数!是不是很厉害?下面我将给大家用 PHP 代码演示一个生成真正随机数的例子:
// 声明取一个区间内随机数的函数
functiongetRandom($min=1,$max=10){$params=['min'=>$min,// 最小数'max'=>$max,// 最大数'num'=>1,// 只取1个随机数'format'=>'plain',// 返回格式'col'=>1,// 整数列 填 1 即可'base'=>10// 进制数 一般取十进制];$params_str=http_build_query($params);// 调用 Random.org 的接口$ch=curl_init();$url='https://www.random.org/integers/?'.$params_str;curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_HEADER,);curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);$random_info=curl_exec($ch);curl_close($ch);returntrim($random_info);
}
// 获得随机数 并取出中奖人员
$list=['嘉书','小艾','智豪','焕之','少峰'];
$count=count($list);
$winer=$list[getRandom(,$count)];
echo$winer;
运行十几遍,发现分配的确实很随机,很平均。以上代码只起到抛砖引玉的作用,如果想要实现更复杂的要求,至少那个函数是可以拿去复用的~
领取专属 10元无门槛券
私享最新 技术干货