php 实现概率抽奖
PHP 实现概率抽奖的方法
概率抽奖的核心是根据预设的概率分布随机选取奖项。以下是几种常见的实现方式:
权重随机算法
定义一个包含奖项及其概率的数组,通过计算总权重并生成随机数来匹配奖项。

function weightedRandomDraw($prizes) {
$totalWeight = array_sum(array_column($prizes, 'probability'));
$rand = mt_rand(1, $totalWeight);
$currentWeight = 0;
foreach ($prizes as $prize) {
$currentWeight += $prize['probability'];
if ($rand <= $currentWeight) {
return $prize;
}
}
return null;
}
// 示例奖项配置
$prizes = [
['name' => '一等奖', 'probability' => 10],
['name' => '二等奖', 'probability' => 20],
['name' => '三等奖', 'probability' => 70]
];
$result = weightedRandomDraw($prizes);
概率区间法
将概率转换为累计区间,通过随机数落在哪个区间决定奖项。

function probabilityRangeDraw($prizes) {
$ranges = [];
$start = 0;
foreach ($prizes as $prize) {
$end = $start + $prize['probability'];
$ranges[] = [
'name' => $prize['name'],
'start' => $start,
'end' => $end
];
$start = $end;
}
$random = mt_rand(1, 100);
foreach ($ranges as $range) {
if ($random > $range['start'] && $random <= $range['end']) {
return $range['name'];
}
}
return null;
}
// 示例配置(概率总和应为100)
$prizes = [
['name' => '特等奖', 'probability' => 1],
['name' => '一等奖', 'probability' => 5],
['name' => '二等奖', 'probability' => 15],
['name' => '参与奖', 'probability' => 79]
];
$result = probabilityRangeDraw($prizes);
动态概率调整
在多次抽奖后降低高价值奖项的概率,需结合数据库记录已发放数量。
function dynamicProbabilityDraw($prizes) {
// 假设从数据库获取已发放数量
$issued = ['grand_prize' => 2, 'first_prize' => 10];
foreach ($prizes as &$prize) {
if ($prize['id'] === 'grand_prize' && $issued['grand_prize'] >= 5) {
$prize['probability'] = 0; // 大奖已达上限
}
// 其他动态调整逻辑...
}
return weightedRandomDraw($prizes);
}
注意事项
- 概率总和应合理(通常按100%或1000等整数比例)
- 高并发场景需考虑原子操作,如Redis的DECR命令
- 重要奖项建议记录中奖日志到数据库
- 前端可增加动画效果增强体验
性能优化建议
对于高频抽奖场景,可预先生成概率分布表:
function buildProbabilityMap($prizes) {
$map = [];
$index = 0;
foreach ($prizes as $prize) {
$count = $prize['probability'] * 100; // 放大精度
for ($i = 0; $i < $count; $i++) {
$map[] = $prize;
}
}
shuffle($map);
return $map;
}
// 初始化时生成
$probabilityMap = buildProbabilityMap($prizes);
// 抽奖时直接取随机元素
$result = $probabilityMap[array_rand($probabilityMap)];
以上方法可根据实际需求组合使用,如结合数据库记录实现每日限额或用户去重功能。






