博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP实现微信红包拆分算法
阅读量:6612 次
发布时间:2019-06-24

本文共 3515 字,大约阅读时间需要 11 分钟。

算法为自创,非微信官方算法(仅供参考);如测出有问题,请及时反馈。感谢

原文:

CHANGELOG


2018-04-07

  • 修复最后一个红包输出未保留2位数
  • 修复领取的红包金额低于最小红包限制
handle(); * print_r($res); * * @author Flc <2018-04-06 20:09:53> * @see http://flc.ren | http://flc.io | https://github.com/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);

运行结果:

转载地址:http://agaso.baihongyu.com/

你可能感兴趣的文章
《深入理解Android:卷III A》一一3.2音量管理
查看>>
test
查看>>
java基础知识: day7-正则表达式
查看>>
用掘金-Markdown 编辑器写文章
查看>>
iOS开发UI篇--一个侧滑菜单SlidingMenu
查看>>
使用Karate轻松实现自动API测试
查看>>
React
查看>>
TopK 问题
查看>>
jvm 与java内存模型相关简要概念
查看>>
ThinkSNS 最新版功能
查看>>
创建本地YUM源
查看>>
Linux-下载、安装和使用Mozilla Firefox浏览器及LumaQQ软件
查看>>
Linux-系统安全相关命令--passwd;su;umask;chgrp
查看>>
9. SQL -左连接,右连接,全连接,内连接,连接
查看>>
组策略之WMI筛选器
查看>>
我的友情链接
查看>>
树莓派3音频配置
查看>>
使用意图在Activity之间传递数据小插曲__传递自定义的序列化对象
查看>>
我的友情链接
查看>>
Axure 制作app侧滑菜单
查看>>