微信随机生成红包金额算法php版


Posted in PHP onJuly 21, 2016

最近在研究发红包的功能,于是写了个红包的生成算法。

红包生成算法的需求
预先生成所有的红包还是一个请求随机生成一个红包
简单来说,就是把一个大整数m分解(直接以“分为单位,如1元即100)分解成n个小整数的过程,小整数的范围是[min, max]。
最简单的思路,先保底,每个小红包保证有min,然后每个请求都随机生成一个0到(max-min)范围的整数,再加上min就是红包的钱数。
这个算法虽然简单,但是有一个弊端:最后生成的红包可能都是min钱数的。也就是说可能最后的红包都是0.01元的。
另一种方式是预先生成所有红包,这样就比较容易控制了。我选择的是预先生成所有的红包。

理想的红包生成算法
理想的红包生成结果是平均值附近的红包比较多,大红包和小红包的数量比较少。
可以想像下,生成红包的数量的分布有点像正态分布。 

那么如何实现这种平均线附近值比较多的要求呢?
就是要找到一种算法,可以提高平均值附近的概率。那么利用一种”膨胀“再”收缩“的方式来达到这种效果。
先平方,再生成平方范围内的随机数,再开方,那么概率就不再是平均的了。
具体算法:(设置的总钱数,总人数,最大值,最小值要合理)
Php代码

/** 
 * 求一个数的平方 
 * @param $n 
 */ 
function sqr($n){ 
  return $n*$n; 
} 
 
/** 
* 生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐加大。 
* 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。 
*/  
function xRandom($bonus_min,$bonus_max){ 
  $sqr = intval(sqr($bonus_max-$bonus_min)); 
  $rand_num = rand(0, ($sqr-1)); 
  return intval(sqrt($rand_num)); 
} 
 
 
 /** 
 *  
 * @param $bonus_total 红包总额 
 * @param $bonus_count 红包个数 
 * @param $bonus_max 每个小红包的最大额 
 * @param $bonus_min 每个小红包的最小额 
 * @return 存放生成的每个小红包的值的一维数组 
 */  
function getBonus($bonus_total, $bonus_count, $bonus_max, $bonus_min) {  
  $result = array();  
 
  $average = $bonus_total / $bonus_count;  
 
  $a = $average - $bonus_min;  
  $b = $bonus_max - $bonus_min;  
 
  //  
  //这样的随机数的概率实际改变了,产生大数的可能性要比产生小数的概率要小。  
  //这样就实现了大部分红包的值在平均数附近。大红包和小红包比较少。  
  $range1 = sqr($average - $bonus_min);  
  $range2 = sqr($bonus_max - $average);  
 
  for ($i = 0; $i < $bonus_count; $i++) {  
    //因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。  
    //当随机数>平均值,则产生小红包  
    //当随机数<平均值,则产生大红包  
    if (rand($bonus_min, $bonus_max) > $average) {  
      // 在平均线上减钱  
      $temp = $bonus_min + xRandom($bonus_min, $average);  
      $result[$i] = $temp;  
      $bonus_total -= $temp;  
    } else {  
      // 在平均线上加钱  
      $temp = $bonus_max - xRandom($average, $bonus_max);  
      $result[$i] = $temp;  
      $bonus_total -= $temp;  
    }  
  }  
  // 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。  
  while ($bonus_total > 0) {  
    for ($i = 0; $i < $bonus_count; $i++) {  
      if ($bonus_total > 0 && $result[$i] < $bonus_max) {  
        $result[$i]++;  
        $bonus_total--;  
      }  
    }  
  }  
  // 如果钱是负数了,还得从已生成的小红包中抽取回来  
  while ($bonus_total < 0) {  
    for ($i = 0; $i < $bonus_count; $i++) {  
      if ($bonus_total < 0 && $result[$i] > $bonus_min) {  
        $result[$i]--;  
        $bonus_total++;  
      }  
    }  
  }  
  return $result;  
} 
$bonus_total = 200; 
$bonus_count = 100; 
$bonus_max = 10;//此算法要求设置的最大值要大于平均值 
$bonus_min = 1; 
$result_bonus = getBonus($bonus_total, $bonus_count, $bonus_max, $bonus_min); 
$total_money = 0; 
$arr = array(); 
foreach ($result_bonus as $key => $value) { 
  $total_money += $value; 
  if(isset($arr[$value])){ 
    $arr[$value] += 1; 
  }else{ 
    $arr[$value] = 1; 
  } 
   
} 
//输出总钱数,查看是否与设置的总数相同 
echo $total_money; 
//输出所有随机红包值 
var_dump($result_bonus); 
//统计每个钱数的红包数量,检查是否接近正态分布 
ksort($arr); 
var_dump($arr);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
防止用户利用PHP代码DOS造成用光网络带宽
Mar 01 PHP
php根据操作系统转换文件名大小写的方法
Feb 24 PHP
PHP中is_file不能替代file_exists的理由
Mar 04 PHP
PHP读取CURL模拟登录时生成Cookie文件的方法
Nov 04 PHP
PHP过滤黑名单关键字的方法
Dec 01 PHP
php强制运行广告的方法
Dec 01 PHP
Yii框架上传图片用法总结
Mar 28 PHP
PHP魔术方法以及关于独立实例与相连实例的全面讲解
Oct 18 PHP
PHP读取文本文件并逐行输出该行使用最多的字符与对应次数的方法
Nov 25 PHP
PHP基于SMTP协议实现邮件发送实例代码
Apr 27 PHP
php面向对象程序设计中self与static的区别分析
May 21 PHP
php 原生分页
Apr 01 PHP
PHP简单读取PDF页数的实现方法
Jul 21 #PHP
基于PHP微信红包的算法探讨
Jul 21 #PHP
php中preg_replace_callback函数简单用法示例
Jul 21 #PHP
PHP获取客户端及服务器端IP的封装类
Jul 21 #PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
Jul 21 #PHP
PHP获取当前文件的父目录方法汇总
Jul 21 #PHP
功能强大的php分页函数
Jul 20 #PHP
You might like
php 调用远程url的六种方法小结
2009/11/02 PHP
PHP面向对象概念
2011/11/06 PHP
php实现的xml操作类
2016/01/15 PHP
javascript第一课
2007/02/27 Javascript
javascript中的void运算符语法及使用介绍
2013/03/10 Javascript
Javascript 遮罩层和加载效果代码
2013/08/01 Javascript
javascript 终止函数执行操作
2014/02/14 Javascript
Node.js中的缓冲与流模块详细介绍
2015/02/11 Javascript
JQuery节点元素属性操作方法
2015/06/11 Javascript
JS+CSS实现自动切换的网页滑动门菜单效果代码
2015/09/14 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
vue-cli中打包图片路径错误的解决方法
2017/10/26 Javascript
jQuery中内容过滤器简单用法示例
2018/03/31 jQuery
详解微信小程序缓存--缓存时效性
2019/05/02 Javascript
vue实现表格过滤功能
2019/09/27 Javascript
JS实现多选框的操作
2020/06/24 Javascript
JS将指定的某个字符全部转换为其他字符实例代码
2020/10/13 Javascript
python中的五种异常处理机制介绍
2014/09/02 Python
利用Python实现简单的相似图片搜索的教程
2015/04/23 Python
怎样使用Python脚本日志功能
2016/08/14 Python
python itchat实现微信自动回复的示例代码
2017/08/14 Python
Python实现Logger打印功能的方法详解
2017/09/01 Python
python如何变换环境
2020/07/21 Python
如何使用python写截屏小工具
2020/09/29 Python
CSS3的Flexbox布局的简明入门指南
2016/04/08 HTML / CSS
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
英国最受欢迎的平价女士时装零售商:Roman Originals
2019/11/02 全球购物
YSL圣罗兰美妆俄罗斯官网:Yves Saint Lauret RU
2020/09/23 全球购物
vue实现倒计时功能
2021/03/24 Vue.js
酒鬼酒广告词
2014/03/21 职场文书
满月酒主持词
2014/03/27 职场文书
环境整治工作方案
2014/05/18 职场文书
社区党建工作汇报材料
2014/08/14 职场文书
2014年客房服务员工作总结
2014/11/18 职场文书
MySql 缓存查询原理与缓存监控和索引监控介绍
2021/07/02 MySQL
Python序列化模块JSON与Pickle
2022/06/05 Python