微信随机生成红包金额算法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+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
Feb 15 PHP
Uchome1.2 1.5 代码学习 common.php
Apr 24 PHP
php函数的常用方法及注意之处小结
Jul 10 PHP
基于php权限分配的实现代码
Apr 28 PHP
PHP自动识别字符集并完成转码详解
Aug 02 PHP
PHP验证信用卡卡号是否正确函数
May 27 PHP
Yii编程开发常见调用技巧集锦
Jul 15 PHP
PHP微信公众号开发之微信红包实现方法分析
Jul 14 PHP
PHP编程快速实现数组去重的方法详解
Jul 22 PHP
PHP实现的CURL非阻塞调用类
Jul 26 PHP
php实现微信企业付款到个人零钱功能
Oct 09 PHP
PHP PDOStatement::fetchColumn讲解
Jan 31 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魔术方法与魔术变量、内置方法与内置变量的深入分析
2013/06/03 PHP
深入PHP5中的魔术方法详解
2013/06/17 PHP
destoon整合UCenter图文教程
2014/06/21 PHP
PHP程序员必须清楚的问题汇总
2014/12/18 PHP
PHP使用NuSOAP调用Web服务的方法
2015/07/18 PHP
tp5框架内使用tp3.2分页的方法分析
2019/05/05 PHP
2020最新版 PhpStudy V8.1版本下载安装使用详解
2020/10/30 PHP
网易JS面试题与Javascript词法作用域说明
2010/11/09 Javascript
javascript管中窥豹 形参与实参浅析
2011/12/17 Javascript
jquerydom对象的事件隐藏显示和对象数组示例
2013/12/10 Javascript
jquery中对于批量deferred的处理方法
2014/01/22 Javascript
js获取窗口相对于屏幕左边和上边的位置坐标
2014/05/15 Javascript
简单了解JavaScript操作XPath的一些基本方法
2016/06/03 Javascript
JS实现按钮控制计时开始和停止功能
2017/07/27 Javascript
jquery 一键复制到剪切板的实例
2017/09/20 jQuery
《javascript少儿编程》location术语总结
2018/05/27 Javascript
前端天气插件tpwidget使用方法详解
2019/06/24 Javascript
原生js添加一个或多个类名的方法分析
2019/07/30 Javascript
Vue 2.0双向绑定原理的实现方法
2019/10/23 Javascript
Python实现全角半角转换的方法
2014/08/18 Python
在Python的Django框架中simple-todo工具的简单使用
2015/05/30 Python
python中不能连接超时的问题及解决方法
2018/06/10 Python
基于wxPython的GUI实现输入对话框(1)
2019/02/27 Python
详解python的argpare和click模块小结
2019/03/31 Python
Python小程序之在图片上加入数字的代码
2019/11/26 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
2020/09/21 Python
pandas map(),apply(),applymap()区别解析
2021/02/24 Python
举例详解HTML5中使用JSON格式提交表单
2015/06/16 HTML / CSS
HTML5 Canvas入门学习教程
2016/03/17 HTML / CSS
解释一下钝化(Swap out)
2016/12/26 面试题
华为python面试题
2016/05/03 面试题
八年级英语教学反思
2014/01/09 职场文书
小班下学期幼儿评语
2014/12/30 职场文书
关于Python中进度条的六个实用技巧分享
2022/04/05 Python
详解Flutter和Dart取消Future的三种方法
2022/04/07 Java/Android
《仙剑客栈2》第一弹正式宣传片公开 年内发售
2022/04/07 其他游戏