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编写PDF文档生成器
Oct 09 PHP
php数据库连接
Oct 09 PHP
PHP 定界符 使用技巧
Jun 14 PHP
C#使用PHP服务端的Web Service通信实例
Apr 08 PHP
php判断数组元素中是否存在某个字符串的方法
Jun 14 PHP
五款PHP代码重构工具推荐
Oct 14 PHP
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
Nov 19 PHP
smarty内置函数foreach用法实例
Jan 22 PHP
PHP简单实现文本计数器的方法
Apr 28 PHP
php解决约瑟夫环算法实例分析
Sep 30 PHP
Thinkphp5.0框架视图view的循环标签用法示例
Oct 12 PHP
PHP网站常见安全漏洞,及相应防范措施总结
Mar 01 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
用session做客户验证时的注意事项
2006/10/09 PHP
php入门学习知识点三 PHP上传
2011/07/14 PHP
深入apache host的配置详解
2013/06/09 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(六)
2014/06/23 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
2020/04/26 PHP
javascript 面向对象思想 附源码
2009/07/07 Javascript
JQuery 学习笔记 选择器之二
2009/07/23 Javascript
javascript小数计算出现近似值的解决办法
2010/02/06 Javascript
JavaScript ( (__ = !$ + $)[+$] + ({} + $)[_/_] +({} + $)[_/_] )
2011/02/25 Javascript
EditPlus注册码生成器(js代码实现)
2013/03/25 Javascript
JS实现点击登录弹出窗口同时背景色渐变动画效果
2016/03/25 Javascript
基于JS实现密码框(password)中显示文字提示功能代码
2016/05/27 Javascript
Bootstrap 折叠(Collapse)插件用法实例详解
2016/06/01 Javascript
微信js-sdk界面操作接口用法示例
2016/10/12 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
2017/03/04 Javascript
详解vue服务端渲染(SSR)初探
2017/06/19 Javascript
在Vue项目中用fullcalendar制作日程表的示例代码
2019/08/04 Javascript
JS实现简单日历特效
2020/01/03 Javascript
vue实现购物车选择功能
2020/01/10 Javascript
vue-cli点击实现全屏功能
2020/03/07 Javascript
javascript使用Blob对象实现的下载文件操作示例
2020/04/18 Javascript
Python生成密码库功能示例
2017/05/23 Python
Python中使用pypdf2合并、分割、加密pdf文件的代码详解
2019/05/21 Python
对YOLOv3模型调用时候的python接口详解
2019/08/26 Python
Python项目跨域问题解决方案
2020/06/22 Python
公务员平时考核实施方案
2014/03/11 职场文书
服装设计专业毕业生求职信
2014/04/09 职场文书
教师敬业奉献模范事迹材料
2014/05/18 职场文书
建筑节能汇报材料
2014/08/22 职场文书
党的群众路线教育实践活动学习笔记
2014/11/05 职场文书
学校拾金不昧表扬信
2015/01/16 职场文书
个人催款函范文
2015/06/23 职场文书
给校长的建议书范文
2015/09/14 职场文书
2016公司新年问候语
2015/11/11 职场文书
MySQL不使用order by实现排名的三种思路总结
2021/06/02 MySQL