这里只实现了金额计算,业务逻辑需要自行处理
<?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);