分享实现PHP红包算法的思路(附开发代码)

 4119

PHP红包算法,根据很多需求的使用场景,如发红包、砍价类需求,这两个功能都有一个同样的特点,如下:

红包

1、总金额

2、红包个数

3、最小红包数量


砍价

1、砍价总金额

2、需要多少人完成砍价(人数根据需求而定)

固定砍价人数

随机砍价人数

指定随机砍价人数

第2点三个规则都需要根据规则得出一个人数

3、最小砍价金额


开发思路

验证参数

最小金额不允许小于0

总金额不允许大于数量乘最小金额


分配金额

取得平均金额(总金额/剩余数量)

分配金额 平均金额小于等于最金额时直接分配最小金额

获取金额幅度比例 最小值不允许小于 -1 最大值不允许大于 1

得出分配金额 幅度计算(平均值*(1+幅度比例))

分配金额判断 分配金额小于最小金额或者分配金额大于 可领取最大金额 ((最小金额+剩余总金额)- (剩余数量×最小金额))时 重新分配金额

剩余最后一个则剩余所有金额都分配


开发代码

  1. <?php
  2.  
  3. /**
  4.  * 发送红包
  5.  * Class sandRed
  6.  */
  7. class sandRed
  8. {
  9.     #红包金额
  10.     protected $amount;
  11.     #红包个数
  12.     protected $num;
  13.     #领取的红包最小金额
  14.     protected $minAmount;
  15.     #红包分配结果
  16.     protected $amountArr = [];
  17.  
  18.     public function __construct($amount, $num = 1, $minAmount = 1)
  19.     {
  20.         $this->amount = $amount;
  21.         $this->num = $num;
  22.         $this->minAmount = $minAmount;
  23.     }
  24.  
  25.     /**
  26.      * 处理返回
  27.      * @return array
  28.      * @throws Exception
  29.      */
  30.     public function handle()
  31.     {
  32.         # 验证
  33.         if ($this->amount < $validAmount = $this->minAmount * $this->num) {
  34.             throw new Exception('红包总金额必须≥'.$validAmount.'元');
  35.         }
  36.         # 分配红包
  37.         $this->allot();
  38.         return $this->amountArr;
  39.     }
  40.  
  41.     /**
  42.      * 分配红包
  43.      */
  44.     protected function allot()
  45.     {
  46.         # 剩余可分配的红包个数
  47.         $num = $this->num;
  48.  
  49.         # 剩余可领取的红包金额
  50.         $amount = $this->amount;
  51.         while ($num >= 1) {
  52.             if ($num == 1) {
  53.                 # 剩余一个的时候,直接取剩余红包
  54.                 $coupon_amount = $this->formattingAmount($amount);
  55.             } else {
  56.  
  57.                 # 平均金额
  58.                 $avgAmount = $this->formattingAmount($amount / $num);
  59.  
  60.                 # 分配金额
  61.                 $countAllotAmount = $this->countAllotAmount($avgAmount, $amount, $num);
  62.  
  63.                 # 剩余的红包的平均金额
  64.                 $coupon_amount = $this->formattingAmount($countAllotAmount);
  65.             }
  66.             # 追加分配金额
  67.             $this->amountArr[] = $coupon_amount;
  68.  
  69.             # 计算剩余金额
  70.             $amount -= $coupon_amount;
  71.  
  72.             $num--;
  73.         }
  74.         # 随机打乱
  75.         // shuffle($this->amountArr);
  76.     }
  77.  
  78.     /**
  79.      * 计算分配的红包金额
  80.      * @param float $avgAmount 每次计算的平均金额
  81.      * @param float $amount 剩余可领取金额
  82.      * @param int $num 剩余可领取的红包个数
  83.      * @return float
  84.      */
  85.     protected function countAllotAmount($avgAmount, $amount, $num)
  86.     {
  87.         # 如果平均金额小于等于最低金额,则直接返回最低金额
  88.         if ($avgAmount <= $this->minAmount) {
  89.             return $this->minAmount;
  90.         }
  91.         # 浮动比率
  92.         $floatingRate = $this->floatingRate();
  93.  
  94.         # 分配金额
  95.         $allotAmount = $avgAmount * (1 + $floatingRate);
  96.  
  97.         # 浮动计算
  98.         $coupon_amount = $this->formattingAmount($allotAmount);
  99.  
  100.         # 如果低于最低金额或超过可领取的最大金额,则重新获取
  101.         if ($coupon_amount < $this->minAmount || $coupon_amount > $this->canReceiveMaxAmount($amount, $num)) {
  102.             return $this->countAllotAmount($avgAmount, $amount, $num);
  103.         }
  104.         return $coupon_amount;
  105.     }
  106.  
  107.     /**
  108.      * 计算分配的红包金额-可领取的最大金额
  109.      * @param $amount
  110.      * @param $num
  111.      * @return float|int
  112.      */
  113.     protected function canReceiveMaxAmount($amount, $num)
  114.     {
  115.         return $this->minAmount + $amount - $num * $this->minAmount;
  116.     }
  117.  
  118.     /**
  119.      * 红包金额浮动比例
  120.      * @return float|int
  121.      */
  122.     protected function floatingRate()
  123.     {
  124.         # 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)
  125.         if (rand(1, 100) <= 60) {
  126.             # 上下幅度70%
  127.             return rand(-70, 70) / 100;
  128.         }
  129.         # 其他情况,上下浮动30%;
  130.         return rand(-30, 30) / 100;
  131.     }
  132.  
  133.     /**
  134.      * 格式化金额,保留2位
  135.      * @param $amount
  136.      * @return string
  137.      */
  138.     protected function formattingAmount($amount)
  139.     {
  140.         return sprintf('%01.2f', round($amount, 2));
  141.     }
  142. }


总金额

  1. $amount = 1;

分配数量

  1. $num = 10;

最小金额

  1. $minAmount = 0.01;
  2.  
  3. $red = new sandRed($amount, $num, $minAmount);
  4.  
  5. $res = $red->handle();
  6. print_r($res);

输出结果 [0.10,0.04,0.08,0.04,0.16,0.14,0.11,0.13,0.11,0.09]

  1. echo array_sum($res);

输出结果 1


本文网址:https://www.zztuku.com/detail-9109.html
站长图库 - 分享实现PHP红包算法的思路(附开发代码)
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐