适用于抽奖程序、随机广告的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 相关文章推荐
玩转图像函数库―常见图形操作
Sep 03 PHP
中国站长站 For Dede4.0 采集规则
May 27 PHP
PHP 截取字符串 分别适合GB2312和UTF8编码情况
Feb 12 PHP
php+mysql数据库实现无限分类的方法
Dec 12 PHP
PHP微信开发之二维码生成类
Jun 26 PHP
PHP简单实现生成txt文件到指定目录的方法
Apr 25 PHP
Linux平台php命令行程序处理管道数据的方法
Nov 10 PHP
php脚本守护进程原理与实现方法详解
Jul 20 PHP
PHP设计模式之简单工厂和工厂模式实例分析
Mar 25 PHP
在Laravel中实现使用AJAX动态刷新部分页面
Oct 15 PHP
php ActiveMQ的安装与使用方法图文教程
Feb 23 PHP
php实现微信和支付宝支付的示例代码
Aug 11 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
日本十大科幻动漫 宇宙骑士垫底,第一已成经典
2020/03/04 日漫
十天学会php(3)
2006/10/09 PHP
php 模拟get_headers函数的代码示例
2013/04/27 PHP
PHP解决URL中文GBK乱码问题的两种方法
2014/06/03 PHP
PHP版本的选择5.2.17 5.3.27 5.3.28 5.4 5.5兼容性问题分析
2016/04/04 PHP
详解Laravel视图间共享数据与视图Composer
2016/08/04 PHP
在php7中MongoDB实现模糊查询的方法详解
2017/05/03 PHP
thinkPHP中钩子的使用方法实例分析
2017/11/16 PHP
PHP命令Command模式用法实例分析
2018/08/08 PHP
jquery 如何动态添加、删除class样式方法介绍
2012/11/07 Javascript
javascript使用中为什么10..toString()正常而10.toString()出错呢
2013/01/11 Javascript
Javascript和HTML5利用canvas构建Web五子棋游戏实现算法
2013/07/17 Javascript
用JavaScript显示浏览器客户端信息的超相近教程
2015/06/18 Javascript
利用js判断手机是否安装某个app的多种方案
2017/02/13 Javascript
VUE实现日历组件功能
2017/03/13 Javascript
利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
2017/03/15 Javascript
JS排序之选择排序详解
2017/04/08 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
如何快速解决JS或Jquery ajax异步跨域的问题
2018/01/08 jQuery
微信小程序引入VANT组件的方法步骤
2019/09/19 Javascript
详解Node.JS模块 process
2020/08/31 Javascript
分析python服务器拒绝服务攻击代码
2014/01/16 Python
python中有关时间日期格式转换问题
2019/12/25 Python
Django中的模型类设计及展示示例详解
2020/05/29 Python
Keras 中Leaky ReLU等高级激活函数的用法
2020/07/05 Python
关于Python错误重试方法总结
2021/01/03 Python
微信小程序实现可实时改变转速的css3旋转动画实例代码
2018/09/11 HTML / CSS
新加坡领先的时尚生活方式零售品牌:CHARLES & KEITH
2018/01/16 全球购物
澳大利亚首屈一指的鞋类品牌:Tony Bianco
2018/03/13 全球购物
Solid & Striped官网:美国泳装品牌
2019/06/19 全球购物
信息技术教学反思
2014/02/12 职场文书
2015年党员发展工作总结
2015/05/13 职场文书
爱国主义电影观后感
2015/06/18 职场文书
Nginx设置日志打印post请求参数的方法
2021/03/31 Servers
详解Python中的进程和线程
2021/06/23 Python
MySQL 如何限制一张表的记录数
2021/09/14 MySQL