php版微信红包算法

这里只实现了金额计算,业务逻辑需要自行处理

<?php

/**
 * 微信红包算法
 */
class Hongbao
{
    // 总金额
    private $price;

    // 红包总数
    private $number = 1;

    // 剩余红包金额
    private $availablePrice;

    // 剩余红包数量
    private $numbers;

    // 每个红包最小金额
    private $minPrice = 0.01;

    // 单个可领取最大金额
    private $maxPrice = 200;

    /**
     * 设置相关参数
     * @author guocp
     * @DateTime 2020-09-22T16:32:54+0800
     * @param    float                    $price    [description]
     * @param    int                      $number   [description]
     * @param    float                    $minPrice [description]
     */
    public function setConfig(float $price, int $number, float $minPrice, float $maxPrice)
    {
        // 剩下的、可用的金额,
        $this->price = $this->availablePrice = $price;

        // 红包最小金额
        $this->minPrice = $minPrice;

        // 单个可领取最大金额
        $this->maxPrice = $maxPrice;

        // 剩下红包数
        $this->number = $this->numbers = $number;
    }

    /**
     * 获取红包金额
     * @author guocp
     * @DateTime 2020-09-22T16:33:05+0800
     * @return   [type]                   [description]
     */
    public function getRondPrice()
    {
        // 最后一个红包处理, 剩下的红包钱都是ta的了
        if ($this->numbers === 1) {
            --$this->numbers;

            return bcsub($this->availablePrice, 0, 2);
        }

        // 红包金额 == 个人最大金额 * 红包数时, 随机算法改平均算法
        if (bcdiv($this->price, $this->number, 2) == $this->maxPrice) {
            --$this->numbers;

            $money = bcdiv($this->price, $this->number, 2);

            $this->availablePrice = bcsub($this->availablePrice, $money, 2);

            return $money;
        }

        // 取0-1随机数
        $rand = lcg_value();

        // 当前用户可领取最大金额
        $max = bcmul(bcdiv($this->availablePrice, $this->numbers, 2), 2, 2);

        // 计算出本次领取金额
        $money = bcmul($max, $rand, 2);

        // 领取金额不能超出最大最小限制
        $money = $money <= $this->minPrice ? $this->minPrice : $money;
        $money = $money >= $this->maxPrice ? $this->maxPrice : $money;

        // 转为合法金额(2位小数)
        $money = bcdiv(floor(bcmul($money, 100, 2)), 100, 2);

        // 扣除剩余红包数量
        --$this->numbers;

        // 扣除剩余红包金额
        $this->availablePrice = bcsub($this->availablePrice, $money, 2);

        return $money;
    }
}

// 我是用cli运行测试的
@list($number, $price, $minPrice, $maxPrice) = array_slice($argv, 1);

if (empty($number)) {
    $number = 1;
}
if (empty($price)) {
    $price = 200;
}
if (empty($minPrice)) {
    $minPrice = 0.01;
}
if (empty($maxPrice)) {
    $maxPrice = 200;
}

$list = [];

$hongbao = new Hongbao();
$hongbao->setConfig($price, $number, $minPrice, $maxPrice);

for ($i=0; $i < $number; $i++) {
    $list[$i] = $hongbao->getRondPrice();
}

var_dump($list);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值