PHP概率计算函数汇总


Posted in PHP onSeptember 13, 2015

其实发这篇博感觉并没有什么用,太简单了,会的人不屑看,不会的人自已动动脑子也想到了。但是看着自已的博客已经这么久没更,真心疼~。粗略算下一篇只有代码的水文,会占用OSC至少十几KB的数据库空间呢,但是,一想到乱弹里的然并卵,也就释然了。

<?php
 
/**
 * 概率计算类
 * 可用于抽奖等
 */
class Probability
{
  /**
   * 概率统计数据
   * thing => chance
   */
  var $data = array();
  var $chance_count = 0;
 
  function __construct($initdata = array()){
    if(!empty($initdata)){
      $this->data = $initdata;
      foreach($initdata as $d){
        $this->chance_count += $d['num'];
      }
    }
  }
 
  function addData($name, $chance){
    $this->data[]=array('name'=>$name, 'num'=>$chance);
    $this->chance_count += $chance;
  }
 
  function getOne(){
    $index = rand(0, $this->chance_count);
    foreach($this->data as $d){
      $index = $index-$d['num'];
      if($index<=0){
        return $d['name'];
      }
    }
    return '';
  }
}
 
 
/**
 * 使用示例
 */
$pro=new Probability();
$pro->addData('iphone',10);
$pro->addData('watch',30);
$pro->addData('$18',50);
$pro->addData('thank you',10);
$pro->addData('super big',1);
for($i=0;$i<100;$i++){
  echo $pro->getOne()."\n";
}

这是一个很经典的概率算法函数:

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; 
}

假设:我们有这样一个数组:a奖概率20%,b奖概率30%,c奖概率50%

$prize_arr =array('a'=>20,'b'=>30,'c'=>50);

模拟函数执行过程:

总概率精度为20+30+50=100

第一次数组循环,$procur=20

假设抽取的随机数rand(1,100),假设抽到$randNum=55

if判断-------

如果$randNum<=20,则result=a

否则进入下一循环,总概率精度变为100-20=80

第二次数组循环,$procur=30

假设抽取的随机数rand(1,80),假设抽到$randNum=33

if判断---------

如果$randNum<=30,则result=b

否则进入下一循环,总概率精度变为80-30=50

第三次数组循环,$prosur=50;

假设抽取的随机数rand(1,50),不管怎么抽,随机数都会<或=50,

那么得出result=c;

 因为样本没有改变,虽然可能抽取的随机数不止一个,但是概率是不变的。

或者也可以这样:

function get_rand($arr)
  {
    $pro_sum=array_sum($arr);
    $rand_num=mt_rand(1,$pro_sum);
    $tmp_num=0;
    foreach($arr as $k=>$val)
    {  
      if($rand_num<=$val+$tmp_num)
      {
        $n=$k;
        break;
      }else
      {
        $tmp_num+=$val;
      }
    }
    return $n;
  }

在给大家分享一个抽奖的概率算法

/*
 * 经典的概率算法,
 * $proArr是一个预先设置的数组,
 * 假设数组为:array(100,200,300,400),
 * 开始是从1,1000 这个概率范围内筛选第一个数是否在他的出现概率范围之内, 
 * 如果不在,则将概率空间,也就是k的值减去刚刚的那个数字的概率空间,
 * 在本例当中就是减去100,也就是说第二个数是在1,900这个范围内筛选的。
 * 这样 筛选到最终,总会有一个数满足要求。
 * 就相当于去一个箱子里摸东西,
 * 第一个不是,第二个不是,第三个还不是,那最后一个一定是。
 * 这个算法简单,而且效率非常 高,
 * 关键是这个算法已在我们以前的项目中有应用,尤其是大数据量的项目中效率非常棒。
 */
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;
}
 
 
/*
 * 奖项数组
 * 是一个二维数组,记录了所有本次抽奖的奖项信息,
 * 其中id表示中奖等级,prize表示奖品,v表示中奖概率。
 * 注意其中的v必须为整数,你可以将对应的 奖项的v设置成0,即意味着该奖项抽中的几率是0,
 * 数组中v的总和(基数),基数越大越能体现概率的准确性。
 * 本例中v的总和为100,那么平板电脑对应的 中奖概率就是1%,
 * 如果v的总和是10000,那中奖概率就是万分之一了。
 * 
 */
$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),
);
 
/*
 * 每次前端页面的请求,PHP循环奖项设置数组,
 * 通过概率计算函数get_rand获取抽中的奖项id。
 * 将中奖奖品保存在数组$res['yes']中,
 * 而剩下的未中奖的信息保存在$res['no']中,
 * 最后输出json个数数据给前端页面。
 */
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;
print_r($res['yes']);
PHP 相关文章推荐
PHP+DBM的同学录程序(2)
Oct 09 PHP
MYSQL环境变量设置方法
Jan 15 PHP
深入解读php中关于抽象(abstract)类和抽象方法的问题分析
Jan 03 PHP
php面向对象中static静态属性和静态方法的调用
Feb 08 PHP
php中使用url传递数组的方法
Feb 11 PHP
深入浅出php socket编程
May 13 PHP
给WordPress中的留言加上楼层号的PHP代码实例
Dec 14 PHP
全新Mac配置PHP开发环境教程
Feb 03 PHP
PHPExcel简单读取excel文件示例
May 26 PHP
Yii控制器中filter过滤器用法分析
Jul 15 PHP
PHP实现笛卡尔积算法的实例讲解
Dec 22 PHP
php实现对短信验证码发送次数的限制实例讲解
Mar 04 PHP
整理php防注入和XSS攻击通用过滤
Sep 13 #PHP
教你识别简单的免查杀PHP后门
Sep 13 #PHP
php文件扩展名判断及获取文件扩展名的N种方法
Sep 12 #PHP
php上传功能集后缀名判断和随机命名(强力推荐)
Sep 10 #PHP
ubuntu下配置nginx+php+mysql详解
Sep 10 #PHP
ThinkPHP函数详解之M方法和R方法
Sep 10 #PHP
基于JQuery+PHP编写砸金蛋中奖程序
Sep 08 #PHP
You might like
《星际争霸重制版》兵种对比图鉴
2020/03/02 星际争霸
天津市收音机工业发展史
2021/03/04 无线电
PHP中substr()与explode()函数用法分析
2014/11/24 PHP
php实现将上传word文件转为html的方法
2015/06/03 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
php判断数组是否为空的实例方法
2020/05/10 PHP
javascript高级选择器querySelector和querySelectorAll全面解析
2016/04/07 Javascript
Javascript 跨域知识详细介绍
2016/10/30 Javascript
详解Nodejs的timers模块
2016/12/22 NodeJs
BootStrap学习系列之布局组件(下拉,按钮组[toolbar],上拉)
2017/01/03 Javascript
ionic环境配置及问题详解
2017/06/27 Javascript
实例解析Vue.js下载方式及基本概念
2018/05/11 Javascript
Node.js 使用jade模板引擎的示例
2018/05/11 Javascript
Vue中控制v-for循环次数的实现方法
2018/09/26 Javascript
vue实现微信二次分享以及自定义分享的示例
2019/03/20 Javascript
[01:03:38]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS CIS
2014/05/22 DOTA
[01:10]DOTA2 Supermajor:英雄,由我们见证
2018/05/14 DOTA
python使用递归解决全排列数字示例
2014/02/11 Python
Python中Django框架利用url来控制登录的方法
2015/07/25 Python
Python Selenium Cookie 绕过验证码实现登录示例代码
2018/04/10 Python
django+xadmin+djcelery实现后台管理定时任务
2018/08/14 Python
基于python if 判断选择结构的实例详解
2019/05/06 Python
python GUI实现小球满屏乱跑效果
2019/05/09 Python
Python内置数据类型list各方法的性能测试过程解析
2020/01/07 Python
Django ORM实现按天获取数据去重求和例子
2020/05/18 Python
韩国爱茉莉太平洋化妆品美国站:Amore Pacific US
2016/10/28 全球购物
Wedgwood美国官网:英国骨瓷,精美礼品及家居装饰
2018/02/17 全球购物
英国儿童设计师服装的领先零售商:Base
2019/03/17 全球购物
Java中实现多态的机制
2015/08/09 面试题
机关搬迁方案
2014/05/18 职场文书
医学求职信
2014/05/28 职场文书
2014年“世界无车日”活动方案
2014/09/21 职场文书
领导班子奢靡之风查摆问题及整改措施
2014/09/27 职场文书
办公室班子四风问题对照检查材料
2014/10/04 职场文书
学习雷锋精神活动总结
2015/02/06 职场文书
听课评课活动心得体会
2016/01/15 职场文书