首页 » php » 正文

使用 PHP 解决机率和权重问题

//有一个百货公司办了一个抽奖活动,一等奖的中奖率是3%,二等奖是5%,三等奖是10%,纪念奖是20%。
//处理这个需求,一般的程序员会采用如下的逻辑:
$randKey = mt_rand(1, 100);
$key = 0;
if ($randKey <= 3) {
$key = 1;
} elseif ($randKey <= 3 + 5) {
$key = 2;
} elseif ($randKey <= 3 + 5 + 10) {
$key = 3;
} elseif ($randKey <= 3 + 5 + 10 + 20) {
$key = 4;
}

//这段程序似乎有些复杂,我们可以简化一下它:
$prizeInfo = array(
0 => 62,
1 => 3,
2 => 5,
3 => 10,
4 => 20
);
$randKey = mt_rand(1, 100);
$radix = 0;
foreach ($prizeInfo as $key => $values) {
$radix += $values;
if ($randKey <= $radix) {
break;
}
}

//权重和机率类似,只是概率总值不固定,我们只想直观的用一个数字的大小来表示想给它多大的机会。
//我们修改一下需求,一等奖的权重是5,二等奖是10,三等奖是20,纪念奖是50,没有奖励是100。
//实际上,稍微修改一下逻辑,我们就可以处理这个问题了:
$prizeInfo = array(
0 => 100,
1 => 5,
2 => 10,
3 => 20,
4 => 50
);
$randKey = mt_rand(1, array_sum($prizeInfo));
$radix = 0;
foreach ($prizeInfo as $key => $values) {
$radix += $values;
if ($randKey <= $radix) {
break;
}
}

//但是实际上,我们在处理更复杂的需求时会发现,即使我们使用了 PHP 中号称更好用线性分布更平均的 mt_rand,统计结果看起来,也不是那么随机,或许这是源于 PHP 本身的问题。
//我在设计杀死怪物时按照权重掉落物品的逻辑时,就遇到了这样的问题。
//稍作处理后,结果稍微满意了些,基本上,我只是扩大了随机范围,扰乱了权重的顺序。
$prizeInfo = array(
0 => 100,
1 => 5,
2 => 10,
3 => 20,
4 => 50
);
$keys = array_keys($prizeInfo);
shuffle($keys);
$randKey = rand(1, array_sum($prizeInfo));
$radix = 0;
foreach ($keys as $key) {
$radix += $prizeInfo[$key];
if ($randKey <= $radix)
{
break;
}
}
//这段逻辑基本上可以应付大多数的权重和机率问题!
//当然,如果你有更复杂更精确的需求,你可能需要自己设计一个特别的算法。

这几个对中奖求概率的很有用,贴出来,分享一下……

发表评论