在開發搶紅包功能時,最關鍵的在於如何將固定總金額隨機拆分成指定份數,且保證每份金額不相同、總和精確等於原始金額。這篇文章將帶你透徹理解 PHP 紅包分配的數學原理與程式碼實作。
假設總金額 10 元,需分給 N 人隨機領取:
核心規律:分配當前紅包時,先預留剩餘紅包所需最低金額(剩餘份數 × 0.01),再在 0.01 到「剩餘總額 - 預留金額」區間取隨機數。
$total = 20; // 紅包總金額
$num = 10; // 分成 10 個紅包
$min = 0.01; // 每人最少 0.01 元
for ($i = 1; $i < $num; $i++) {
// 隨機安全上限 = (剩餘總額 - 預留最低金額) / 剩餘份數
$safe_total = ($total - ($num - $i) * $min) / ($num - $i);
// 以分為單位取隨機整數,避免浮點數誤差
$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 元
...
第10個紅包:2.54 元,余額 0 元
<div class="demo">
<button>生成10個紅包,總金額20元</button>
</div>
<div id="result"></div>
<script>
$(function(){
$("button").click(function(){
$.ajax({
type: 'POST',
url: 'bao.php',
dataType: 'json',
beforeSend: function(){ $("#result").html('正在分配紅包...'); },
success: function(json){
if(json.msg == 1){
var str = '';
$.each(json.res, function(index, item){
str += '<p>第<span>'+item.i+'</span>個紅包,金額<span>'+item.money+'</span>元,余額<span>'+item.total+'</span>元</p>';
});
$("#result").html(str);
}else{
$("#result").html('資料錯誤!');
}
}
});
});
});
</script>
<?php
header("Content-Type: application/json;charset=utf-8");
$total = 20; $num = 10; $min = 0.01;
for ($i = 1; $i < $num; $i++) {
$safe_total = ($total - ($num - $i) * $min) / ($num - $i);
$money = mt_rand($min * 100, $safe_total * 100) / 100;
$total -= $money;
$arr['res'][$i] = ['i' => $i, 'money' => $money, 'total' => $total];
}
$arr['res'][$num] = ['i' => $num, 'money' => $total, 'total' => 0];
$arr['msg'] = 1;
echo json_encode($arr);
?>
實際上線時,建議在發紅包階段預先完成金額分配並存入資料庫(含紅包 ID、金額、狀態),用戶搶紅包時隨機抽取一筆「未領取」紅包並標記為已領取,可有效避免併發問題與金額誤差。