适用于抽奖程序、随机广告的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版(5)
Oct 09 PHP
BBS(php &amp; mysql)完整版(三)
Oct 09 PHP
php中的实现trim函数代码
Mar 19 PHP
php htmlentities和htmlspecialchars 的区别
Aug 18 PHP
PHP 采集程序原理分析篇
Mar 05 PHP
PHP Session_Regenerate_ID函数双释放内存破坏漏洞
Jan 27 PHP
解析php安全性问题中的:Null 字符问题
Jun 21 PHP
php禁止浏览器使用缓存页面的方法
Nov 07 PHP
php array_slice 取出数组中的一段序列实例
Nov 04 PHP
php mysql_list_dbs()函数用法示例
Mar 29 PHP
PHP创建单例后台进程的方法示例
May 23 PHP
CMSPRESS 10行代码搞定 PHP无限级分类2
Mar 30 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
微信公众平台开发之天气预报功能
2015/08/31 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
2018/02/08 PHP
使用javascript实现雪花飘落的效果
2015/01/13 Javascript
javascript验证邮件地址和MX记录的方法
2015/06/16 Javascript
Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法
2017/09/20 Javascript
Vue中在新窗口打开页面及Vue-router的使用
2018/06/13 Javascript
vscode中vue-cli项目es-lint的配置方法
2018/07/30 Javascript
VUE-Table上绑定Input通过render实现双向绑定数据的示例
2018/08/27 Javascript
在js代码拼接dom对象到页面上的模板总结
2018/10/21 Javascript
vue spa应用中的路由缓存问题与解决方案
2019/05/31 Javascript
vue-cli history模式实现tomcat部署报404的解决方式
2019/09/06 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
2020/07/22 Javascript
Vue实现手机号、验证码登录(60s禁用倒计时)
2020/12/19 Vue.js
[01:57]2016完美“圣”典风云人物:国士无双专访
2016/12/04 DOTA
python在Windows8下获取本机ip地址的方法
2015/03/14 Python
Python表示矩阵的方法分析
2017/05/26 Python
全面了解Nginx, WSGI, Flask之间的关系
2018/01/09 Python
Python学习之Django的管理界面代码示例
2018/02/10 Python
python3第三方爬虫库BeautifulSoup4安装教程
2018/06/19 Python
python将txt文件读入为np.array的方法
2018/10/30 Python
PyQt5 如何让界面和逻辑分离的方法
2020/03/24 Python
Python读入mnist二进制图像文件并显示实例
2020/04/24 Python
Python自动巡检H3C交换机实现过程解析
2020/08/14 Python
python 实现弹球游戏的示例代码
2020/11/17 Python
Python实现随机爬山算法
2021/01/29 Python
HTML5拖拽的简单实例
2016/05/30 HTML / CSS
canvas 基础之图像处理的使用
2020/04/10 HTML / CSS
Bose美国官网:购买Bose耳机和音箱
2019/03/10 全球购物
英国123鲜花网站:123 Flowers
2019/07/07 全球购物
《桥》教学反思
2014/04/09 职场文书
竞选班干部演讲稿600字
2014/08/20 职场文书
社区国庆节活动总结
2015/03/23 职场文书
2015年乡镇科普工作总结
2015/05/13 职场文书
消防宣传语大全
2015/07/13 职场文书
个人工作总结怎么写?
2019/04/09 职场文书
mysqldump进行数据备份详解
2022/07/15 MySQL