#### 1. 前言 --- 在公司的一个项目中有红包抽奖活动,其中有拼手气红包。 在网上找了别人封装的红包分配算法,但是都存在问题,索性就自己手写了一个 #### 2. PHP 拼手气红包分配算法 --- ```php /** * 拼手气红包分配算法 * * @param $money 金额 * @param $count 数量 */ function redAlgorithm($money, $count) { // 参数校验 if ($count * 0.01 > $money) { throw new \Exception("单个红包不能低于0.01元"); } // 存放随机红包 $redpack = []; // 未分配的金额 $surplus = $money; for ($i = 1; $i <= $count; $i++) { // 安全金额 $safeMoney = $surplus - ($count - $i) * 0.01; // 平均金额 $avg = $i == $count ? $safeMoney : bcdiv($safeMoney, ($count - $i), 2); // 随机红包 $rand = $avg > 0.01 ? mt_rand(1, $avg * 100) / 100 : 0.01; // 剩余红包 $surplus = bcsub($surplus, $rand, 2); $redpack[] = $rand; } // 平分剩余红包 $avg = bcdiv($surplus, $count, 2); for ($n = 0; $n < count($redpack); $n++) { $redpack[$n] = bcadd($redpack[$n], $avg, 2); $surplus = bcsub($surplus, $avg, 2); } // 如果还有红包没有分配完时继续分配 if ($surplus > 0) { // 随机抽取分配好的红包,将剩余金额分配进去 $keys = array_rand($redpack, $surplus * 100); // array_rand 第二个参数为 1 时返回的是下标而不是数组 $keys = is_array($keys) ? $keys : [$keys]; foreach ($keys as $key) { $redpack[$key] = bcadd($redpack[$key], 0.01, 2); $surplus = bcsub($surplus, 0.01, 2); } } // 红包分配结果 return $redpack; } ```