当前位置: 首页 > 后端技术 > PHP

PHP实现微信红包拆分算法

时间:2023-03-30 05:15:42 PHP

算法自创,非微信官方算法(仅供参考);测试中如有问题,请及时反馈。感谢原文:http://flc.ren/2018/04/701.htmlCHANGELOG2018-04-07修复最后一个红包输出不保留2位修复收到的红包数量低于最低红包限额handle();*print_r($res);**@authorFlc<2018-04-0620:09:53>*@seehttp://flc.ren|http://flc.io|https://github.com/flc1125*/classCoupon{/***红包金额**@varfloat*/protected$amount;/***红包数量**@varint*/protected$num;/***最低领取红包数量**@varfloat*/protected$coupon_min;/***红包发放结果**@vararray*/protected$items=[];/***初始化**@paramfloat$amount红包金额(单位:元)最多保留2位小数*@paramint$num红包数量*@paramfloat$coupon_min最少收到的红包金额通过每个*/publicfunction__construct($amount,$num=1,$coupon_min=0.01){$this->amount=$amount;$this->num=$数;$this->coupon_min=$coupon_min;}/***处理返回**@returnarray*/publicfunctionhandle(){//A.Validateif($this->amount<$validAmount=$this->coupon_min*$this->num){thrownewException('红包总额必须≥'.$validAmount.'元');}//B.分配红包$this->apportion();返回['items'=>$this->items,];}/***分配红包*/protectedfunctionapportion(){$num=$this->num;//可分配的剩余红包数$amount=$this->amount;//剩余可领取的红包数量while($num>=1){//当还剩一个时,直接拿剩余的红包if($num==1){$coupon_amount=$this->decimal_number($金额);}else{$avg_amount=$this->decimal_number($amount/$num);//平均剩余红包数量$coupon_amount=$this->decimal_number($this->calcCouponAmount($avg_a安装,$金额,$num));$this->items[]=$coupon_amount;//额外分配$amount-=$coupon_amount;--$数;}洗牌($this->items);//随机洗牌}/***计算分配的红包数量**@paramfloat$avg_amount每次计算的平均数量*@paramfloat$amount剩余可领取数量*@paramint$num数量剩余可领取红包数量**@returnfloat*/protectedfunctioncalcCouponAmount($avg_amount,$amount,$num){//如果平均金额小于等于最小金额,则直接返回最小金额金额if($avg_amount<=$this->coupon_min){return$this->coupon_min;}//浮动计算$coupon_amount=$this->decimal_number($avg_amount*(1+$this->apportionRandRatio()));//如果低于最低可申领金额或超过最高可领取金额,则重新获取{返回$this->calcCouponAmount($avg_am数量,$金额,$num);}返回$coupon_amount;}/***计算派发的红包数量-最大可领取数量**@paramfloat$amount*@paramint$num*/protectedfunctioncalcCouponAmountMax($amount,$num){return$this->coupon_min+$amount-$num*$this->coupon_min;}/***红包金额的浮动比例*/protectedfunctionapportionRandRatio(){//60%的几率得到剩余的平均值一个大红包价值(可能是正数也可能是负数)if(rand(1,100)<=60){返回兰特(-70,70)/100;//上下70%}returnrand(-30,30)/100;//其他情况,上下浮动30%;}/***格式化金额,保留2位**@paramfloat$amount**@returnfloat*/protectedfunctiondecimal_number($amount){returnsprintf('%01.2f',round($amount,2));}}//示例$coupon=newCoupon(200,5,30);$res=$coupon->handle();print_r($res);运行结果:http://www.dooccn.com/php7/#i...