#### 1. 前言 --- 在公司的一個(gè)項(xiàng)目中有紅包抽獎(jiǎng)活動(dòng),其中有拼手氣紅包。 在網(wǎng)上找了別人封裝的紅包分配算法,但是都存在問(wèn)題,索性就自己手寫(xiě)了一個(gè) #### 2. PHP 拼手氣紅包分配算法 --- ```php /** * 拼手氣紅包分配算法 * * @param $money 金額 * @param $count 數(shù)量 */ function redAlgorithm($money, $count) { // 參數(shù)校驗(yàn) if ($count * 0.01 > $money) { throw new \Exception("單個(gè)紅包不能低于0.01元"); } // 存放隨機(jī)紅包 $redpack = []; // 未分配的金額 $surplus = $money; for ($i = 1; $i <= $count; $i++) { // 安全金額 $safeMoney = $surplus - ($count - $i) * 0.01; // 平均金額 $avg = $i == $count ? $safeMoney : bcdiv($safeMoney, ($count - $i), 2); // 隨機(jī)紅包 $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); } // 如果還有紅包沒(méi)有分配完時(shí)繼續(xù)分配 if ($surplus > 0) { // 隨機(jī)抽取分配好的紅包,將剩余金額分配進(jìn)去 $keys = array_rand($redpack, $surplus * 100); // array_rand 第二個(gè)參數(shù)為 1 時(shí)返回的是下標(biāo)而不是數(shù)組 $keys = is_array($keys) ? $keys : [$keys]; foreach ($keys as $key) { $redpack[$key] = bcadd($redpack[$key], 0.01, 2); $surplus = bcsub($surplus, 0.01, 2); } } // 紅包分配結(jié)果 return $redpack; } ```