核心需求:給定總金額 $total 和紅包個數 $num,隨機生成 $num 個金額,滿足:
1. 所有人都能領到(最小 0.01 元)
2. 總和精確等於 $total
3. 金額有差異(隨機性)
設最小單位 $min = 0.01。第 i 個紅包(1 ≤ i < num)分配時:
remain = num - ireserved = remain * minmax = (total - reserved) / (remain + 1)(平均值)money = rand(min*100, max*100) / 100total -= money最後一個紅包直接獲得剩餘所有金額。
$total = 20; // 總金額 20 元
$num = 10; // 10 個紅包
$min = 0.01; // 最小 1 分
for ($i = 1; $i < $num; $i++) {
$remain = $num - $i;
$safe_total = ($total - $remain * $min) / ($remain + 1); // 安全上限
$money = mt_rand($min * 100, $safe_total * 100) / 100; // 分為單位隨機
$total -= $money;
echo "第 $i 個紅包:$money 元,余額:$total 元
";
}
echo "第 $num 個紅包:$total 元,余額:0 元";
第1個紅包:2.08 元,余額:17.92 元 第2個紅包:1.81 元,余額:16.11 元 第3個紅包:0.15 元,余額:15.96 元 第4個紅包:1.61 元,余額:14.35 元 第5個紅包:1.11 元,余額:13.24 元 第6個紅包:1.51 元,余額:11.73 元 第7個紅包:1.21 元,余額:10.52 元 第8個紅包:2.58 元,余額:7.94 元 第9個紅包:5.40 元,余額:2.54 元 第10個紅包:2.54 元,余額:0 元
CREATE TABLE `red_packet` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`batch_id` VARCHAR(32) NOT NULL COMMENT '紅包批次號',
`amount` INT UNSIGNED NOT NULL COMMENT '金額(分)',
`status` TINYINT DEFAULT 0 COMMENT '0待領取 1已領取',
`receiver_id` BIGINT UNSIGNED NULL COMMENT '領取用戶ID',
`receive_time` DATETIME NULL,
INDEX `idx_batch_status` (`batch_id`, `status`)
);
該算法已在多個項目生產環境驗證,穩定可靠。完整源碼可下載參考。