PHP实现微信红包分包算法源码(抛物线的模型) 本文共有4472个字,关键词: ``` rewardArray=array(); } #执行红包生成算法 public function splitReward($rewardMoney,$rewardNum,$scatter=100) { #传入红包金额和数量 $this->rewardMoney=$rewardMoney; $this->rewardNum=$rewardNum; $this->scatter=$scatter; $this->realscatter=$this->scatter/100; /* *前言:今天我突然这样一想,比如要把1个红包分给N个人,实际上就是相当于要得到N个百分比数据 * 条件是这N个百分比之和=100/100。这N个百分比的平均值是1/N。 * 并且这N个百分比数据符合一种正态分布(多数值比较靠近平均值) *观点:微信红包里很多0.01的红包,我觉得这是微信程序里的人为控制,目的是为了防止总红包数超过总额,先分了几个0.01的红包。 * 不然不管是以随机概率还是正态分布都很难会出现非常多的0.01元红包。 */ #我的思路:正如上面说的,比如:1个红包发给5个人,我要得出5个小数,它们的和是1,他们的平均值是1/5 #计算出发出红包的平均概率值、精确到小数4位。即上面的1/N值。 $avgRand=round(1/$this->rewardNum,4); #红包的向平均数集中的分布正像数学上的抛物线。抛物线y=ax2,|a|越大则抛物线的开口就越小,|a|越小则抛物线的开口就越大,a>0时开口向上,我们这都是正数,就以a>0来考虑吧。 #程序里的$scatter值即为上方的a,此值除以100,当做100为基准, #通过开方(数学里的抛物线模型,开方可缩小变化值)得出一个小数字较多(小数字多即小红包多)的随机分布,据此生成随机数 $randArr=array(); while(count($randArr)<$rewardNum) { $t=round(sqrt(mt_rand(1,10000)/$this->realscatter)); $randArr[]=$t; } #计算当前生成的随机数的平均值,保留4位小数 $randAll=round(array_sum($randArr)/count($randArr),4); #为将生成的随机数的平均值变成我们要的1/N,计算一下生成的每个随机数都需要除以的值。我们可以在最后一个红包进行单独处理,所以此处可约等于处理。 $mixrand=round($randAll/$avgRand,4); #对每一个随机数进行处理,并剩以总金额数来得出这个红包的金额。 $rewardArr=array(); foreach($randArr as $key=>$randVal) { $randVal=round($randVal/$mixrand,4); $rewardArr[]=round($this->rewardMoney*$randVal,2); } #对比红包总数的差异、修正最后一个大红包 sort($rewardArr); $rewardAll=array_sum($rewardArr); $rewardArr[$this->rewardNum-1]=$this->rewardMoney-($rewardAll-$rewardArr[$this->rewardNum-1]); rsort($rewardArr); #对红包进行排序一下以方便在前台图示展示 foreach($rewardArr as $k=>$value) { $t=$k%2; if($t) array_push($this->rewardArray,$value); else array_unshift($this->rewardArray,$value); } $rewardArr=NULL; return $this->rewardArray; } } $money=1000; #总共要发的红包数; $people=50; #总共要发的人数 $scatter=100; #分散度 $reward=new reward(); $rewardArr=$reward->splitReward($money,$people,$scatter); echo "发放红包个数:{$people},红包总金额{$money}元。下方所有红包总额之和:".array_sum($reward->rewardArray).'元。下方用图展示红包的分布'; echo ''; echo "红包金额图示"; foreach($rewardArr as $val) { #线条长度计算 $width=intval($people*$val*300/$money); echo "{$val}"; } echo ""; ?> ``` 测试结果[10块分5个包]: ``` ["0.13","2.66","3.05","3.04","1.12"] ["0.68","2.19","2.93","2.69","1.51"] ["1.12","1.89","2.7","2.65","1.64"] ["0.44","2.5","2.98","2.65","1.43"] ["0.94","1.6","3.07","2.95","1.44"] ["1.28","2.26","2.45","2.41","1.6"] ["0.37","2.3","2.7","2.6","2.03"] ["1.38","2.03","2.37","2.36","1.86"] ["1.39","1.77","2.68","2.49","1.67"] ["0.53","2.22","3.13","2.22","1.9"] ["1.16","2.04","2.6","2.4","1.8"] ["1.37","2.01","2.91","2.16","1.55"] ["1.27","2.09","2.45","2.2","1.99"] ["0.74","2.06","2.66","2.61","1.93"] ["0.86","1.84","3.35","2.5","1.45"] ["0.18","2.16","2.98","2.59","2.09"] ["0.75","2.19","2.61","2.52","1.93"] ["0.86","2.46","2.65","2.55","1.48"] ["1.02","1.62","3.16","2.99","1.21"] ["0.86","2.14","2.96","2.45","1.59"] ``` × yihong (๑>ڡ<)☆谢谢老板~ 2元 5元 10元 50元 100元 任意金额 2元 使用微信扫描二维码完成支付 版权声明:本文为作者原创,如需转载须联系作者本人同意,未经作者本人同意不得擅自转载。 PHP 2019-11-04 评论 2457 次浏览