栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > PHP

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

PHP 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

红包

1.总金额
2.红包个数
3.最小红包数量

砍价

1.砍价总金额
2.需要多少人完成砍价(人数根据需求而定)

  • 固定砍价人数
  • 随机砍价人数
  • 指定随机砍价人数
    第2点三个规则都需要根据规则得出一个人数

3.最小砍价金额

开发思路

验证参数
最小金额不允许小于0
总金额不允许大于数量乘最小金额
分配金额

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

分配金额 平均金额小于等于最金额时直接分配最小金额
获取金额幅度比例 最小值不允许小于 -1 最大值不允许大于 1
得出分配金额 幅度计算(平均值*(1+幅度比例))
分配金额判断 分配金额小于最小金额或者分配金额大于 可领取最大金额 ((最小金额+剩余总金额)- (剩余数量×最小金额))时 重新分配金额
剩余最后一个则剩余所有金额都分配

开发代码

amount = $amount;
 $this->num = $num;
 $this->minAmount = $minAmount;
    }

    
    public function handle()
    {
 # 验证
 if ($this->amount < $validAmount = $this->minAmount * $this->num) {
     throw new Exception('红包总金额必须≥'.$validAmount.'元');
 }
 # 分配红包
 $this->allot();
 return $this->amountArr;
    }

    
    protected function allot()
    {
 # 剩余可分配的红包个数
 $num = $this->num;

 # 剩余可领取的红包金额
 $amount = $this->amount;
 while ($num >= 1) {
     if ($num == 1) {
  # 剩余一个的时候,直接取剩余红包
  $coupon_amount = $this->formattingAmount($amount);
     } else {

  # 平均金额
  $avgAmount = $this->formattingAmount($amount / $num);

  # 分配金额
  $countAllotAmount = $this->countAllotAmount($avgAmount, $amount, $num);

  # 剩余的红包的平均金额
  $coupon_amount = $this->formattingAmount($countAllotAmount);
     }
     # 追加分配金额
     $this->amountArr[] = $coupon_amount;

     # 计算剩余金额
     $amount -= $coupon_amount;

     $num--;
 }
 # 随机打乱
 // shuffle($this->amountArr);
    }

    
    protected function countAllotAmount($avgAmount, $amount, $num)
    {
 # 如果平均金额小于等于最低金额,则直接返回最低金额
 if ($avgAmount <= $this->minAmount) {
     return $this->minAmount;
 }
 # 浮动比率
 $floatingRate = $this->floatingRate();

 # 分配金额
 $allotAmount = $avgAmount * (1 + $floatingRate);

 # 浮动计算
 $coupon_amount = $this->formattingAmount($allotAmount);

 # 如果低于最低金额或超过可领取的最大金额,则重新获取
 if ($coupon_amount < $this->minAmount || $coupon_amount > $this->canReceiveMaxAmount($amount, $num)) {
     return $this->countAllotAmount($avgAmount, $amount, $num);
 }
 return $coupon_amount;
    }

    
    protected function canReceiveMaxAmount($amount, $num)
    {
 return $this->minAmount + $amount - $num * $this->minAmount;
    }

    
    protected function floatingRate()
    {
 # 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)
 if (rand(1, 100) <= 60) {
     # 上下幅度70%
     return rand(-70, 70) / 100;
 }
 # 其他情况,上下浮动30%;
 return rand(-30, 30) / 100;
    }

    
    protected function formattingAmount($amount)
    {
 return sprintf('%01.2f', round($amount, 2));
    }
}
  • 总金额
$amount = 1;
  • 分配数量
$num = 10;
  • 最小金额
$minAmount = 0.01;

$red = new sandRed($amount, $num, $minAmount);

$res = $red->handle();
print_r($res);
  • 输出结果 [0.10,0.04,0.08,0.04,0.16,0.14,0.11,0.13,0.11,0.09]
echo array_sum($res);
  • 输出结果 1
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/262187.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号