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实现下载文件的两种方法
Jul 05 PHP
PHP.ini中配置屏蔽错误信息显示和保存错误日志的例子
May 12 PHP
PHP动态规划解决0-1背包问题实例分析
Mar 23 PHP
php 批量查询搜狗sogou代码分享
May 17 PHP
PHP实现全角字符转为半角方法汇总
Jul 09 PHP
Yii2基于Ajax自动获取表单数据的方法
Aug 10 PHP
PHP实现统计在线人数功能示例
Oct 15 PHP
PHP连接MySQL进行增、删、改、查操作
Feb 19 PHP
PHP中Laravel 关联查询返回错误id的解决方法
Apr 01 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
php自定义排序uasort函数示例【二维数组按指定键值排序】
Jun 19 PHP
php写入txt乱码的解决方法
Sep 17 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
zend framework配置操作数据库实例分析
2012/12/06 PHP
五款PHP代码重构工具推荐
2014/10/14 PHP
php blowfish加密解密算法
2016/07/02 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
JS效率个人经验谈(8-15更新),加入range技巧
2007/01/09 Javascript
不用AJAX和IFRAME,说说真正意义上的ASP+JS无刷新技术
2008/09/25 Javascript
监控 url fragment变化的js代码
2010/04/19 Javascript
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
jquery滚动到顶部底部代码
2015/04/20 Javascript
javascript创建含数字字母的随机字符串方法总结
2016/08/01 Javascript
js判断文件格式及大小的简单实例(必看)
2016/10/11 Javascript
node学习记录之搭建web服务器教程
2017/02/16 Javascript
五分钟搞懂Vuex实用知识(小结)
2019/08/12 Javascript
微信小程序如何实现点击图片放大功能
2020/01/21 Javascript
使用next.js开发网址缩短服务的方法
2020/06/17 Javascript
详解Node.JS模块 process
2020/08/31 Javascript
树莓派中python获取GY-85九轴模块信息示例
2013/12/05 Python
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
Python守护进程用法实例分析
2015/06/04 Python
Python 基础知识之字符串处理
2017/01/06 Python
Python人脸识别第三方库face_recognition接口说明文档
2019/05/03 Python
python格式化输出保留2位小数的实现方法
2019/07/02 Python
Python列表与元组的异同详解
2019/07/02 Python
利用Python的folium包绘制城市道路图的实现示例
2020/08/24 Python
Python OpenCV中的numpy与图像类型转换操作
2020/12/11 Python
HTML5操作WebSQL数据库的实例代码
2017/08/26 HTML / CSS
Java方面的关于数组和继承的笔面试题
2015/09/18 面试题
外贸销售员求职的自我评价
2013/11/23 职场文书
周年庆典邀请函范文
2014/01/23 职场文书
银行优秀员工事迹
2014/02/06 职场文书
2014年祖国生日寄语
2014/09/19 职场文书
大学生自我推荐信范文
2015/03/24 职场文书
2015年乡镇发展党员工作总结
2015/03/31 职场文书
详解Go语言中Get/Post请求测试
2022/06/01 Golang
python运行脚本文件的三种方法实例
2022/06/25 Python