600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > PHP 实现微信红包拆分的算法

PHP 实现微信红包拆分的算法

时间:2022-06-22 18:21:09

相关推荐

PHP 实现微信红包拆分的算法

<?php/*** 红包分配算法** @example*$coupon = new Coupon(200, 5);*$res = $coupon->handle();*print_r($res);** @author Flc <-04-06 20:09:53>* @see http://flc.ren | http://flc.io | /flc1125*/class Coupon{/*** 红包金额** @var float*/protected $amount;/*** 红包个数** @var int*/protected $num;/*** 领取的红包最小金额** @var float*/protected $coupon_min;/*** 红包分配结果** @var array*/protected $items = [];/*** 初始化** @param float $amount红包金额(单位:元)最多保留2位小数* @param int $num 红包个数* @param float $coupon_min 每个至少领取的红包金额*/public function __construct($amount, $num = 1, $coupon_min = 0.01){$this->amount = $amount;$this->num = $num;$this->coupon_min = $coupon_min;}/*** 处理返回** @return array*/public function handle(){// A. 验证if ($this->amount < $validAmount = $this->coupon_min * $this->num) {throw new Exception('红包总金额必须≥'.$validAmount.'元');}// B. 分配红包$this->apportion();return ['items' => $this->items,];}/*** 分配红包*/protected function apportion(){$num = $this->num; // 剩余可分配的红包个数$amount = $this->amount; //剩余可领取的红包金额while ($num >= 1) {// 剩余一个的时候,直接取剩余红包if ($num == 1) {$coupon_amount = $this->decimal_number($amount);} else {$avg_amount = $this->decimal_number($amount / $num); // 剩余的红包的平均金额$coupon_amount = $this->decimal_number($this->calcCouponAmount($avg_amount, $amount, $num));}$this->items[] = $coupon_amount; // 追加分配$amount -= $coupon_amount;--$num;}shuffle($this->items); //随机打乱}/*** 计算分配的红包金额** @param float $avg_amount 每次计算的平均金额* @param float $amount剩余可领取金额* @param int $num 剩余可领取的红包个数** @return float*/protected function calcCouponAmount($avg_amount, $amount, $num){// 如果平均金额小于等于最低金额,则直接返回最低金额if ($avg_amount <= $this->coupon_min) {return $this->coupon_min;}// 浮动计算$coupon_amount = $this->decimal_number($avg_amount * (1 + $this->apportionRandRatio()));// 如果低于最低金额或超过可领取的最大金额,则重新获取if ($coupon_amount < $this->coupon_min|| $coupon_amount > $this->calcCouponAmountMax($amount, $num)) {return $this->calcCouponAmount($avg_amount, $amount, $num);}return $coupon_amount;}/*** 计算分配的红包金额-可领取的最大金额** @param float $amount* @param int $num*/protected function calcCouponAmountMax($amount, $num){return $this->coupon_min + $amount - $num * $this->coupon_min;}/*** 红包金额浮动比例*/protected function apportionRandRatio(){// 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)if (rand(1, 100) <= 60) {return rand(-70, 70) / 100; // 上下幅度70%}return rand(-30, 30) / 100; // 其他情况,上下浮动30%;}/*** 格式化金额,保留2位** @param float $amount** @return float*/protected function decimal_number($amount){return sprintf('%01.2f', round($amount, 2));}}// 例子$coupon = new Coupon(200, 5, 30);$res = $coupon->handle();print_r($res);

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。