首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實現可配置中獎機率的抽獎演算法(陣列權重法)

     編輯:PHP 綜合知識

核心思路:陣列擴展法

將獎項按機率展開為陣列元素,再用 shuffle() 打亂順序,最後 array_rand() 取一個。簡單直觀,適合獎項固定、總量可控的場景。

完整實現代碼

<?php
/**
 * 抽獎函數
 * @param int $total 總樣本基數,越大機率越精確
 * @return mixed 中獎等級或「謝謝惠顧」
 */
function getReward($total = 1000) {
    // 定義各獎項機率(百分比)
    $win1 = floor((0.12 * $total) / 100);  // 一等獎 0.12%
    $win2 = floor((3 * $total) / 100);     // 二等獎 3%
    $win3 = floor((12 * $total) / 100);    // 三等獎 12%
    $other = $total - $win1 - $win2 - $win3; // 未中獎

    $pool = array();

    // 依機率填充獎池
    for ($i = 0; $i < $win1; $i++) { $pool[] = 1; }
    for ($i = 0; $i < $win2; $i++) { $pool[] = 2; }
    for ($i = 0; $i < $win3; $i++) { $pool[] = 3; }
    for ($i = 0; $i < $other; $i++) { $pool[] = '謝謝惠顧'; }

    // 打亂並抽取
    shuffle($pool);
    return $pool[array_rand($pool)];
}

// 使用範例
$data = getReward();
echo "抽獎結果:$data";
?>

機率驗證測試

<?php
$stats = array(1 => 0, 2 => 0, 3 => 0, '謝謝惠顧' => 0);
$rounds = 100000;
for ($i = 0; $i < $rounds; $i++) {
    $stats[getReward()]++;
}
foreach ($stats as $k => $v) {
    echo "$k: $v (" . round($v/$rounds*100, 2) . "%)\n";
}
?>

輸出會非常接近理論值(0.12%、3%、12%、84.88%)。

優缺點分析

優點缺點
代碼極簡,無需引入第三方庫記憶體佔用隨 $total 線性增長
機率直觀,修改百分比即時生效$total 過大(>100萬)會明顯拖慢效能
適合獎項固定、並發不極高的活動不支援動態權重(如庫存扣減即時調整機率)

進階替代方案:累積權重法(O(1) 記憶體)

<?php
function getRewardWeighted(array $prizes) {
    // $prizes = ['一等獎' => 0.12, '二等獎' => 3, '三等獎' => 12, '謝謝惠顧' => 84.88];
    $total = array_sum($prizes);
    $rand = mt_rand(1, $total * 10000) / 10000; // 放大 10000 倍避免浮點誤差
    $accum = 0;
    foreach ($prizes as $name => $weight) {
        $accum += $weight;
        if ($rand <= $accum) return $name;
    }
    return '謝謝惠顧'; // 理論不會走到這
}
?>

優點:常數記憶體、支援動態權重、效能穩定。生產環境高併發抽獎建議採用此法或 Redis Lua 腳本保證原子性。

安全性補充

  • 前端不可信,所有抽獎邏輯必須在後端執行
  • 配合 session 或 Redis 記錄用戶抽獎次數,防刷
  • 重要獎項建議加入「二次驗證」(手機驗證碼、實名認證)再發放
  • 記錄完整抽獎日誌(用戶、時間、IP、結果)供稽核
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved