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 相关文章推荐
在数据量大(超过10万)的情况下
Jan 15 PHP
php 随机生成10位字符代码
Mar 26 PHP
linux系统上支持php的 iconv()函数的方法
Oct 01 PHP
php数组函数序列之array_search()- 按元素值返回键名
Nov 04 PHP
避免Smarty与CSS语法冲突的方法
Mar 02 PHP
php封装的连接Mysql类及用法分析
Dec 10 PHP
详解PHP安装mysql.so扩展的方法
Dec 31 PHP
php 解决扫描二维码下载跳转问题
Jan 13 PHP
php实现websocket实时消息推送
Mar 30 PHP
PHP模糊查询技术实例分析【附源码下载】
Mar 07 PHP
laravel 创建命令行命令的图文教程
Oct 23 PHP
PHP项目多语言配置平台实现过程解析
May 18 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
PHP实现对二维数组某个键排序的方法
2016/09/14 PHP
Firebug 字幕文件JSON地址获取代码
2009/10/28 Javascript
jquery获得option的值和对option进行操作
2013/12/13 Javascript
node.js中的fs.symlink方法使用说明
2014/12/15 Javascript
JavaScript中的分号插入机制详细介绍
2015/02/11 Javascript
JavaScript实现在标题栏上显示当前日期的方法
2015/03/19 Javascript
JQuery页面地址处理插件jqURL详解
2015/05/03 Javascript
理解JS事件循环
2016/01/07 Javascript
利用CSS3在Angular中实现动画
2016/01/15 Javascript
详解AngularJS过滤器的使用
2016/03/11 Javascript
ES6新特性之Symbol类型用法分析
2017/03/31 Javascript
Angular2使用Angular-CLI快速搭建工程(二)
2017/05/21 Javascript
推荐VSCode 上特别好用的 Vue 插件之vetur
2017/09/14 Javascript
jquery点击回车键实现登录效果并默认焦点的方法
2018/03/09 jQuery
jQuery无冲突模式详解
2019/01/17 jQuery
今天,小程序正式支持 SVG
2019/04/20 Javascript
JavaScript字符串处理常见操作方法小结
2019/11/15 Javascript
小程序角标的添加及绑定购物车数量进行实时更新的实现代码
2020/12/07 Javascript
[00:52]DOTA2第二届亚洲邀请赛预选赛宣传片
2017/01/13 DOTA
python如何实现excel数据添加到mongodb
2015/07/30 Python
Python对CSV、Excel、txt、dat文件的处理
2018/09/18 Python
Python实现从SQL型数据库读写dataframe型数据的方法【基于pandas】
2019/03/18 Python
Python提取PDF内容的方法(文本、图像、线条等)
2019/09/25 Python
python实现把二维列表变为一维列表的方法分析
2019/10/08 Python
css3制作动态进度条以及附加jQuery百分比数字显示
2012/12/13 HTML / CSS
Hotels.com南非:酒店预订
2017/11/02 全球购物
建筑工程技术应届生求职信
2013/11/17 职场文书
采购部岗位职责
2013/11/24 职场文书
部队万能检讨书
2014/02/20 职场文书
化妆品活动策划方案
2014/05/23 职场文书
活动总结报告怎么写
2014/07/03 职场文书
领导四风问题整改措施思想汇报
2014/10/13 职场文书
接收函格式
2015/01/30 职场文书
2015年企业团支部工作总结
2015/05/21 职场文书
2015年统计员个人工作总结
2015/07/23 职场文书
Python机器学习应用之工业蒸汽数据分析篇详解
2022/01/18 Python