一个简单的发红包方法
在这里写了一个简单的产生金额的方法,代码如下:
/** * 根据红包总金额,个数,类型去产生红包金额数组
* @param int $totalValue 红包总金额 单位为分
* @param int $number 红包个数
* @param int $type 红包类型 0为随机手气红包 1为平分红包 默认为0
* @param int $min 每个红包的最小金额 单位为分 默认为1
* @return array|bool false为参数错误 数组为红包的金额数组 每个元素为int型数值 单位为分
*/
function getBags(int $totalValue, int $number, int $type = 0, int $min = 1)
{
//总金额和红包个数校验
if (($totalValue < 1) || ($number < 1)
) {
return false;
}
//总金额应能够满足最小金额
if ($totalValue < $number * $min) {
return false;
}
//一个红包
if ($number == 1) {
return [$totalValue];
}
$result = [];
$usedBags = $lastBag = 0;
//随机手气红包: 产生$number-1个随机数,将0-$totalValue分割成$number份,每一份就是一个红包
if ($type == 0) {
$randPoints = [];
//每一个随机数值的下限是上一个数值+1, 上限是总金额-预留金额, 以确保后面的每个红包金额不小于最小金额
//第一个随机数值的下限是最小金额, 上限是总金额减去$number-1个最小金额
$remainingValue = $totalValue - (($number-1) * $min);
$latestRandPoint = mt_rand($min, $remainingValue);
$randPoints[] = $latestRandPoint;
$result[] = $latestRandPoint;
$usedBags += $latestRandPoint;
//第二个到最后一个随机数值
for ($i=1; $i<$number-1; $i++) {
$remainingValue += $min;
$latestRandPoint = mt_rand($latestRandPoint+1, $remainingValue);
$randPoints[] = $latestRandPoint;
//当前红包的金额 = 当前随机值 - 上一个随机值
$bag = $latestRandPoint - $randPoints[$i-1];
$result[] = $bag;
$usedBags += $bag;
}
} else { //平分红包
$times = $number;
while ($times-1) {
$bag = round($totalValue/$number, 0);
$result[] = $bag;
$usedBags += $bag;
$times--;
}
}
//最后一个红包
$lastBag = $totalValue - $usedBags;
$result[] = $lastBag;
return $result;
}
测试 (注意金额单位是分)
$result = getBags(1000, 5, 0);var_dump($result);
输出
array(5) { [0]=> int(25) [1]=> int(199) [2]=> int(379) [3]=> int(137) [4]=> int(260) }
这里的核心思想,就是 把总金额$totalValue看成一个从0出发,总长度为总金额的区间,然后在(0, $totalValue) 这个区间中,找出 $number - 1 个随机浮点数,将这个区间或者线段,分隔成 $number 部分,每一个部分的长度,就是一个红包的金额大小。
时间复杂度是O(n)。
这里只提供一种分配的思路,没有考虑到兼顾"公平"的策略,比如限制某个红包最大金额之类的。所以有可能出现5个人分10块钱的红包,有四个人都是最小金额0.01,另一个人9.96这种极端情况。至于"公平性",就涉及到一些更复杂的算法策略了。
以上是 一个简单的发红包方法 的全部内容, 来源链接: utcz.com/z/514150.html