本文介紹一種經典的 PHP 抽獎概率算法,核心邏輯基於「概率空間遞減」原理:將所有獎項概率權重累加為總基數,在 1 到總基數範圍內生成隨機數,依次遍歷獎項,若隨機數落在當前獎項的概率區間內則中獎,否則從總基數中扣除該獎項權重,繼續下一輪篩選。這種「箱子摸球」式算法保證必有結果產出,時間複雜度 O(n),極適合高併發大數據量場景。
function get_rand($proArr) {
$result = '';
$proSum = array_sum($proArr); // 總概率基數
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum); // 在剩餘概率空間內取隨機數
if ($randNum <= $proCur) {
$result = $key; // 命中當前獎項
break;
} else {
$proSum -= $proCur; // 概率空間縮減,進入下一輪
}
}
unset($proArr);
return $result;
}
關鍵點:使用 mt_rand() 而非 rand(),前者基於梅森旋轉算法,速度更快、隨機性更好;循環中動態縮減 $proSum 實現「不歸位抽樣」邏輯。
獎項陣列採用二維結構,包含 id、獎品名稱、權重值 v:
$prize_arr = array(
'0' => array('id'=>1, 'prize'=>'平板電腦', 'v'=>1),
'1' => array('id'=>2, 'prize'=>'數碼相機', 'v'=>5),
'2' => array('id'=>3, 'prize'=>'音箱設備', 'v'=>10),
'3' => array('id'=>4, 'prize'=>'4G優盤', 'v'=>12),
'4' => array('id'=>5, 'prize'=>'10Q幣', 'v'=>22),
'5' => array('id'=>6, 'prize'=>'下次沒准就能中哦', 'v'=>50),
);
權重總和為 100,平板電腦中獎概率 1%。若需萬分之一精度,將總基數擴大至 10000 並按比例調整各權重即可。設置 v=0 可禁用某獎項。
$arr[$val['id']] = $val['v'] 映射 id 到權重get_rand($arr) 獲取中獎 id{'yes': 中獎獎品, 'no': [未中獎列表]}該算法代碼簡潔(核心不足 20 行)、邏輯清晰、性能優異,是 PHP 抽獎系統的首選方案。實際部署時建議將權重配置外置到資料庫或配置文件,支援運營動態調整概率無需改代碼。