單抽獎(jiǎng)算法(設(shè)置庫存))
注意: probability(概率)之和必須100下面方法為簡(jiǎn)單沒有庫存public function draw() { $draw_list [ [ name 空獎(jiǎng)(0-80), probability 80.00 ], [ name 5積分(80-90), probability 10.00 ], [ name 10積分(90-98), probability 8.00 ], [ name 20積分(98-100), probability 2.00 ], ]; // 生成一個(gè)0到100之間的隨機(jī)數(shù) $randomNum random_int(0, 100); $currentProbability 0; foreach ($draw_list as $draw_info) { $currentProbability $draw_info[probability]; if ($randomNum $currentProbability) { $draw_info[currentProbability] $currentProbability; $draw_info[randomNum] $randomNum; $draw_result $draw_info; break; } } $this-success(請(qǐng)求成功!, $draw_result); }含有庫存寫法public function draw_test() { $draw_list [ [ name 空獎(jiǎng)(0-80), probability 80.00, stock 0 ], [ name 5積分(80-90), probability 10.00, stock 1 ], [ name 10積分(90-98), probability 9.9999999, stock 0 ], [ name 20積分(98-100), probability 0.0000001, stock 1 ], ]; // 修改這里調(diào)整支持的小數(shù)位數(shù) $scale 100000000; // 整數(shù)溢出安全校驗(yàn) $maxExpectTotalWeight 100 * $scale; // 預(yù)留1/2安全余量防止后續(xù)分?jǐn)倷?quán)重后溢出 if ($maxExpectTotalWeight PHP_INT_MAX / 2) { $this-error(scale配置過大存在整數(shù)溢出風(fēng)險(xiǎn)請(qǐng)調(diào)小scale值); } $emptyTotalWeight 0; $validList []; foreach ($draw_list as $item) { $p (float)$item[probability]; $intWeight (int)round($p * $scale); if ($item[stock] 0) { $validList[] [ name $item[name], probability $item[probability], //保留原始概率 weight $intWeight, stock $item[stock] ]; } else { $emptyTotalWeight $intWeight; } } // 邊界全部獎(jiǎng)品庫存為0 if (empty($validList)) { $this-error(暫無可用獎(jiǎng)品); } // 將庫存0的獎(jiǎng)項(xiàng)權(quán)重分?jǐn)偟接行И?jiǎng)品 if ($emptyTotalWeight 0) { $validCount count($validList); $avgAdd (int)($emptyTotalWeight / $validCount); $remainder $emptyTotalWeight % $validCount; //余數(shù)補(bǔ)到最后一項(xiàng) foreach ($validList as $idx $v) { $v[weight] $avgAdd; if ($idx $validCount - 1) { $v[weight] $remainder; } } unset($v); } $totalWeight array_sum(array_column($validList, weight)); // 極端保護(hù)總權(quán)重不能小于1 if ($totalWeight 1) { $this-error(獎(jiǎng)品權(quán)重合計(jì)異常); } $rand mt_rand(1, $totalWeight); $currentWeight 0; $draw_result null; foreach ($validList as $row) { $currentWeight $row[weight]; if ($rand $currentWeight) { $draw_result $row; $draw_result[rand] $rand; $draw_result[totalWeight] $totalWeight; break; } } $this-success(請(qǐng)求成功!, $draw_result); }