zoukankan      html  css  js  c++  java
  • PHP微信红包生成算法的程序源码(用抛物线的模型实现)

    代码如下:

     1 <?php
     2 /*
     3  * 红包生成随机算法
     4  */
     5 header("Content-type:text/html;charset=utf-8");
     6 date_default_timezone_set('PRC');
     7 
     8 #红包生成的算法程序
     9 class reward
    10 {
    11     public $rewardMoney;       #红包金额、单位元
    12     public $rewardNum;               #红包数量
    13     public $scatter;           #分散度值1-10000
    14     public $rewardArray;       #红包结果集
    15 
    16     #初始化红包类
    17     public function __construct()
    18     {
    19         $this->rewardArray = array();
    20     }
    21 
    22     #执行红包生成算法
    23     public function splitReward($rewardMoney, $rewardNum, $scatter = 100)
    24     {
    25         #传入红包金额和数量
    26         $this->rewardMoney = $rewardMoney;
    27         $this->rewardNum = $rewardNum;
    28         $this->scatter = $scatter;
    29         $this->realscatter = $this->scatter / 100;
    30         /*
    31          *前言:今天我突然这样一想,比如要把1个红包分给N个人,实际上就是相当于要得到N个百分比数据
    32          *     条件是这N个百分比之和=100/100。这N个百分比的平均值是1/N。
    33          *     并且这N个百分比数据符合一种正态分布(多数值比较靠近平均值)
    34          *观点:微信红包里很多0.01的红包,我觉得这是微信程序里的人为控制,目的是为了防止总红包数超过总额,先分了几个0.01的红包。
    35          *     不然不管是以随机概率还是正态分布都很难会出现非常多的0.01元红包。
    36          */
    37         #我的思路:正如上面说的,比如:1个红包发给5个人,我要得出5个小数,它们的和是1,他们的平均值是1/5
    38         #计算出发出红包的平均概率值、精确到小数4位。即上面的1/N值。
    39         $avgRand = round(1 / $this->rewardNum, 4);
    40         #红包的向平均数集中的分布正像数学上的抛物线。抛物线y=ax2,|a|越大则抛物线的开口就越小,|a|越小则抛物线的开口就越大,a>0时开口向上,我们这都是正数,就以a>0来考虑吧。
    41         #程序里的$scatter值即为上方的a,此值除以100,当做100为基准,
    42         #通过开方(数学里的抛物线模型,开方可缩小变化值)得出一个小数字较多(小数字多即小红包多)的随机分布,据此生成随机数
    43         $randArr = array();
    44         while (count($randArr) < $rewardNum) {
    45             $t = round(sqrt(mt_rand(1, 10000) / $this->realscatter));
    46             $randArr[] = $t;
    47         }
    48         #计算当前生成的随机数的平均值,保留4位小数
    49         $randAll = round(array_sum($randArr) / count($randArr), 4);
    50         #为将生成的随机数的平均值变成我们要的1/N,计算一下生成的每个随机数都需要除以的值。我们可以在最后一个红包进行单独处理,所以此处可约等于处理。
    51         $mixrand = round($randAll / $avgRand, 4);
    52         #对每一个随机数进行处理,并剩以总金额数来得出这个红包的金额。
    53         $rewardArr = array();
    54         foreach ($randArr as $key => $randVal) {
    55             $randVal = round($randVal / $mixrand, 4);
    56             $rewardArr[] = round($this->rewardMoney * $randVal, 2);
    57         }
    58         #对比红包总数的差异、修正最后一个大红包
    59         sort($rewardArr);
    60         $rewardAll = array_sum($rewardArr);
    61         $rewardArr[$this->rewardNum - 1] = $this->rewardMoney - ($rewardAll - $rewardArr[$this->rewardNum - 1]);
    62         rsort($rewardArr);
    63         #对红包进行排序一下以方便在前台图示展示
    64         foreach ($rewardArr as $k => $value) {
    65             $t = $k % 2;
    66             if ($t) array_push($this->rewardArray, $value);
    67             else array_unshift($this->rewardArray, $value);
    68         }
    69         $rewardArr = NULL;
    70         return $this->rewardArray;
    71     }
    72 }
    73 
    74 $money = 1000;    #总共要发的红包数;
    75 $people = 50;     #总共要发的人数
    76 $scatter = 100;    #分散度
    77 $reward = new reward();
    78 $rewardArr = $reward->splitReward($money, $people, $scatter);
    79 echo "发放红包个数:{$people},红包总金额{$money}元。下方所有红包总额之和:" . array_sum($reward->rewardArray) . '元。下方用图展示红包的分布';
    80 echo '<hr>';
    81 echo "<table style='font-size:12px;600px;border:1px solid #ccc;text-align:left;'><tr><td>红包金额</td><td>图示</td></tr>";
    82 foreach ($rewardArr as $val) {
    83     #线条长度计算
    84     $width = intval($people * $val * 300 / $money);
    85     echo "<tr><td>{$val}</td><td width='500px;text-align:left;'><hr style='{$width}px;height:3px;border:none;border-top:3px double red;margin:0 auto 0 0px;'></td></tr>";
    86 }
    87 echo "</table>";
    88 ?>

    在上传的文件里需要改一下:

    $t=round(sqrt(mt_rand(1,10000)/$this->realscatter));,要控制值不为能0,我改成了1,没有测试,可能需要改大点,因为开方后的数值会缩小。

    也可以对这行的值直接进行ceil处理, 就不会出现红包为0的数了。

    对于scatter的值我没有多做研究,不过根据抛物线的数学模型,这个值的意义可以使抛物线的张口放大缩小,即可以让红包的值分散或者集中。

    链接:https://www.php.cn/php-weizijiaocheng-393575.html

  • 相关阅读:
    项目总结—校园办公管理系统(SSM框架搭建)
    sssp-webservce_restful
    angular 中怎么获取路径上的参数 参考:https://docs.angularjs.org/api/ng/service/$location
    spring mvc 解决json 不能转换的问题
    在 html中怎么获取中的参数
    弹框,图标
    sssp maven pom
    spring中 的MD5 加密
    angularjs 整合 bootstrap
    深入理解Java包装类与自动拆装箱
  • 原文地址:https://www.cnblogs.com/clubs/p/11950560.html
Copyright © 2011-2022 走看看