适用于抽奖程序、随机广告的PHP概率算法实例


Posted in PHP onApril 09, 2014

那么我们在程序里必然会设计到算法,即按照一定的概率让用户获得奖品。先来看两个概率算法函数。

算法一

/**
 * 全概率计算
 *
 * @param array $p array('a'=>0.5,'b'=>0.2,'c'=>0.4)
 * @return string 返回上面数组的key
 */
function random($ps){
    static $arr = array();
    $key = md5(serialize($ps));
    if (!isset($arr[$key])) {
        $max = array_sum($ps);
        foreach ($ps as $k=>$v) {
            $v = $v / $max * 10000;
            for ($i=0; $i<$v; $i++) $arr[$key][] = $k;
        }
    }
    return $arr[$key][mt_rand(0,count($arr[$key])-1)];
} 

算法二
function get_rand($proArr) { 
    $result = ''; 
    //概率数组的总概率精度
    $proSum = array_sum($proArr); 
    //概率数组循环
    foreach ($proArr as $key => $proCur) { 
        $randNum = mt_rand(1, $proSum); 
        if ($randNum <= $proCur) { 
            $result = $key; 
            break; 
        } else { 
            $proSum -= $proCur; 
        } 
    } 
    unset ($proArr); 
    return $result; 
}

上述代码是一段经典的概率算法,$proArr是一个预先设置的数组,假设数组为:array(100,200,300,400),开始是从1,1000这个概率范围内筛选第一个数是否在他的出现概率范围之内, 如果不在,则将概率空减,也就是k的值减去刚刚的那个数字的概率空间,在本例当中就是减去100,也就是说第二个数是在1,900这个范围内筛选的。这样筛选到最终,总会有一个数满足要求。就相当于去一个箱子里摸东西,第一个不是,第二个不是,第三个还不是,那最后一个一定是。这个算法简单,而且效率非常高,关键是这个算法已在我们以前的项目中有应用,尤其是大数据量的项目中效率非常棒。
接下来我们通过PHP配置奖项。
$prize_arr = array( 
    '0' => array('id'=>1,'prize'=>'平板电脑','v'=>1), 
    '1' => array('id'=>2,'prize'=>'数码相机','v'=>5), 
    '2' => array('id'=>3,'prize'=>'音箱设备','v'=>10), 
    '3' => array('id'=>4,'prize'=>'4G优盘','v'=>12), 
    '4' => array('id'=>5,'prize'=>'10Q币','v'=>22), 
    '5' => array('id'=>6,'prize'=>'下次没准就能中哦','v'=>50), 
);
 
中是一个二维数组,记录了所有本次抽奖的奖项信息,其中id表示中奖等级,prize表示奖品,v表示中奖概率。注意其中的v必须为整数,你可以将对应的奖项的v设置成0,即意味着该奖项抽中的几率是0,数组中v的总和(基数),基数越大越能体现概率的准确性。本例中v的总和为100,那么平板电脑对应的中奖概率就是1%,如果v的总和是10000,那中奖概率就是万分之一了。
每次前端页面的请求,PHP循环奖项设置数组,通过概率计算函数get_rand获取抽中的奖项id。将中奖奖品保存在数组$res['yes']中,而剩下的未中奖的信息保存在$res['no']中,最后输出json个数数据给前端页面。
//如果中奖数据是放在数据库里,这里就需要进行判断中奖数量
//在中1、2、3等奖的,如果达到最大数量的则unset相应的奖项,避免重复中大奖
//code here eg:unset($prize_arr['0'])
foreach ($prize_arr as $key => $val) { 
    $arr[$val['id']] = $val['v']; 
} 
$rid = get_rand($arr); //根据概率获取奖项id
$res['yes'] = $prize_arr[$rid-1]['prize']; //中奖项
//将中奖项从数组中剔除,剩下未中奖项,如果是数据库验证,这里可以省掉
unset($prize_arr[$rid-1]); 
shuffle($prize_arr); //打乱数组顺序
for($i=0;$i<count($prize_arr);$i++){ 
    $pr[] = $prize_arr[$i]['prize']; 
} 
$res['no'] = $pr; 
echo json_encode($res);

为什么我抽不到大奖?

在很多类似的抽奖活动中,参与者往往抽不到大奖,笔者从程序的角度举个例给你看,假如我是抽奖活动的主办方,我设置了6个奖项,每个奖项不同的中奖概率,假如一等奖是一台高级轿车,可是我设置了其中奖概率为0,这意味着什么?这意味着参与抽奖者无论怎么抽,永远也得不到这台高级轿车。而当主办方每次翻动剩下的方块时,参与者会发现一等奖也许就在刚刚抽奖的方块旁边的一个数字下,都怪自己运气差。真的是运气差吗?其实在参与者翻动那个方块时程序已经决定了中奖项,而翻动查看其他方块看到的奖项只是一个烟雾弹,迷惑了观众和参与者。我想看完这篇文章后,您或许会知道电视节目中的翻板抽奖猫腻了,您也许大概再不会去机选双色球了。

PHP 相关文章推荐
PHP nl2br函数 将换行字符转成 &amp;lt;br&amp;gt;
Aug 21 PHP
php str_pad() 将字符串填充成指定长度的字符串
Feb 23 PHP
PHP 面向对象 final类与final方法
May 05 PHP
基于curl数据采集之正则处理函数get_matches的使用
Apr 28 PHP
解析php file_exists无效的解决办法
Jun 26 PHP
解析php扩展php_curl.dll不加载的解决方法
Jun 26 PHP
浅谈PHP调用Webservice思路及源码分享
Jun 04 PHP
php+jQuery.uploadify实现文件上传教程
Dec 26 PHP
PHP的引用详解
Feb 22 PHP
PHP获取当前URL路径的处理方法(适用于多条件筛选列表)
Feb 10 PHP
Yii框架函数简单用法分析
Sep 09 PHP
Vagrant(WSL)+PHPStorm+Xdebu 断点调试环境搭建
Dec 13 PHP
PHP父类调用子类方法的代码例子
Apr 09 #PHP
一个基于phpQuery的php通用采集类分享
Apr 09 #PHP
免费的ip数据库淘宝IP地址库简介和PHP调用实例
Apr 08 #PHP
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
Apr 08 #PHP
PHP设计模式之观察者模式(Observer)详细介绍和代码实例
Apr 08 #PHP
关于PHP的curl开启问题探讨
Apr 08 #PHP
PHP中Session引起的脚本阻塞问题解决办法
Apr 08 #PHP
You might like
针对初学PHP者的疑难问答(1)
2006/10/09 PHP
慎用preg_replace危险的/e修饰符(一句话后门常用)
2013/06/19 PHP
PHP常见漏洞攻击分析
2016/02/21 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
2016/04/26 PHP
PHP使用curl制作简易百度搜索
2016/11/03 PHP
详解php与ethereum客户端交互
2018/04/28 PHP
Gambit vs ForZe BO3 第二场 2.13
2021/03/10 DOTA
MooTools 1.2介绍
2009/09/14 Javascript
用js代码改变单选框选中状态的简单实例
2013/12/18 Javascript
nodejs读取memcache示例分享
2014/01/02 NodeJs
JS小数运算出现多为小数问题的解决方法
2016/06/02 Javascript
Bootstrap响应式侧边栏改进版
2016/09/17 Javascript
canvas学习之API整理笔记(二)
2016/12/29 Javascript
ajax异步请求详解
2017/01/06 Javascript
vue.js 图片上传并预览及图片更换功能的实现代码
2018/08/27 Javascript
使用electron实现百度网盘悬浮窗口功能的示例代码
2018/10/24 Javascript
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
js常用正则表达式集锦
2019/05/17 Javascript
webpack中如何加载静态文件的方法步骤
2019/05/18 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
elementUI 动态生成几行几列的方法示例
2019/07/11 Javascript
[02:09]EHOME夺得首届辉夜杯冠军—现场颁奖仪式
2015/12/28 DOTA
Python实现简易Web爬虫详解
2018/01/03 Python
python生成不重复随机数和对list乱序的解决方法
2018/04/09 Python
对python抓取需要登录网站数据的方法详解
2018/05/21 Python
Python 随机生成测试数据的模块:faker基本使用方法详解
2020/04/09 Python
Python pip install之SSL异常处理操作
2020/09/03 Python
欧洲最大的化妆品连锁公司:Douglas道格拉斯
2017/05/06 全球购物
DBA数据库管理员JAVA程序员架构师必看
2016/02/07 面试题
高校辅导员推荐信范文
2013/12/25 职场文书
竟聘演讲稿范文
2013/12/31 职场文书
《小壁虎借尾巴》教学反思
2014/02/16 职场文书
网络优化专员求职信
2014/05/04 职场文书
任命书模板
2014/06/04 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
68行Python代码实现带难度升级的贪吃蛇
2022/01/18 Python