PHP 概率抽奖算法

Best_ZJJ 2017-10-28 05:35:21
搜到最多的是这个
function get_rand1($proArr) {   
$result = array();
foreach ($proArr as $key => $val) {
$arr[$key] = $val['v'];
}
// 概率数组的总概率
$proSum = array_sum($arr);
asort($arr);
// 概率数组循环
foreach ($arr as $k => $v) {
$randNum = mt_rand(1, $proSum);
if ($randNum <= $v) {
$result = $proArr[$k];
break;
} else {
$proSum -= $v;
}
}
return $result;
}
$arr = array(
array('id'=>1,'name'=>'特等奖','v'=>1),
array('id'=>2,'name'=>'一等奖','v'=>5),
array('id'=>3,'name'=>'二等奖','v'=>10),
array('id'=>4,'name'=>'三等奖','v'=>12),
array('id'=>5,'name'=>'四等奖','v'=>22),
array('id'=>6,'name'=>'没中奖','v'=>50)
);


原理相当于先给你抽1等奖, 如果没中则把总概率空间减少再去抽2等奖… 一直不中就一直抽,最后应为总概率空间的限制肯定会中。
但是感觉这种算法不是很好,不说效率问题, 总感觉概率算法不严谨。如果相邻的两个奖项概率相同且概率又比较大的情况下, 比如一等奖40% 二等奖40% ,因为概率很大,所以感觉还是先抽的比较容易中。请教各位大神有什么更优的算法吗?
...全文
505 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Best_ZJJ 2017-11-01
  • 打赏
  • 举报
回复
引用 2 楼 jip0303 的回复:
效率——仅需走一遍代码……
感觉你的算法太棒了, 效率也高。
jip0303 2017-10-30
  • 打赏
  • 举报
回复
效率——仅需走一遍代码 概率——跟$arr2中规定的一致,你可以随意设置各等级获奖概率,都是公平的 function get_rand2($proArr) { $num = count($proArr); for($i = 0; $i < $num; $i++) { $arr[$i] = $i == 0 ? $proArr[$i]['v'] : $proArr[$i]['v'] + $arr[$i-1]; } var_dump($arr); //$arr 对等各等级奖及之前的中奖概率之和 $proSum = $arr[$num-1] * 100; //为更公平,扩大一下范围 $randNum = mt_rand(1, $proSum) % $arr[$num-1] + 1; //$randNum 一定不大于 $arr[$num-1] 抽奖仅需一次即可 // 概率数组循环 foreach ($arr as $k => $v) { if ($randNum <= $v) { $result = $proArr[$k]; break; } } return $result; } $arr2 = array( //v 表示中奖概率 array('id'=>1,'name'=>'特等奖','v'=>1), array('id'=>2,'name'=>'一等奖','v'=>5), array('id'=>3,'name'=>'二等奖','v'=>10), array('id'=>4,'name'=>'三等奖','v'=>12), array('id'=>5,'name'=>'四等奖','v'=>22), array('id'=>6,'name'=>'没中奖','v'=>50) ); var_dump( get_rand2($arr2) );
xuzuning 2017-10-30
  • 打赏
  • 举报
回复
概率相同(相近)自然结果相近 我们关注的是结果,而不是过程,按你的代码,抽取1000次考察一下
for($i=0; $i<1000; $i++) {
  @$r[get_rand1($arr)['name']]++;
}
asort($r);
print_r($r);
一个可能的结果
Array
(
    [特等奖] => 8
    [一等奖] => 42
    [二等奖] => 103
    [三等奖] => 112
    [四等奖] => 236
    [没中奖] => 499
)
可以看到:是符合预期的 抽取 10000 次的可能结果是
Array
(
    [特等奖] => 96
    [一等奖] => 517
    [二等奖] => 974
    [三等奖] => 1202
    [四等奖] => 2196
    [没中奖] => 5015
)
可见凭感觉是不行的

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧