php中奖概率算法,刮刮卡,大转盘等抽奖算法
/** * 经典的概率算法, * $arrPrize是一个预先设置的奖品数组, * 假设数组为:array(100,200,300,400), * 开始是从1,1000 这个概率范围内筛选第一个数是否在出现概率范围之内, * 如果不在, 则将概率空间的值减去刚刚的那个数字的概率空间, * 在本例当中就是减去100, 也就是说第二个数是在1,900这个范围内筛选的 * 这样筛选到最终,总会有一个数满足要求。 * 就相当于去一个箱子里摸东西,第一个不是, 第二个不是, 第三个还不是, 那最后一个一定是。 * 算法简单而且效率非常高 * @param $arrPrize * @return int|string * @author code.cent123.com */ function getRandPrize($arrPrize) { $result = ''; //总概率 $proSum = array_sum(array_column($arrPrize, 'probability')); //概率数组循环 foreach ($arrPrize as $key => $val) { $randNum = mt_rand(1, $proSum); if ($randNum <= $val['probability']) { $result = $key; break; } else { $proSum -= $val['probability']; } } return $result; }
模拟10000次抽奖,验证中奖概率和分布
/** * 奖项数组 * probability 表示中奖概率 */ $arrPrize = [ ['id' => 1, 'prize' => '一等奖', 'probability' => 1, 'amount' => 10], ['id' => 2, 'prize' => '二等奖', 'probability' => 5, 'amount' => 10], ['id' => 3, 'prize' => '三等奖', 'probability' => 10, 'amount' => 10], ['id' => 4, 'prize' => '四等奖', 'probability' => 12, 'amount' => 10], ['id' => 5, 'prize' => '五等奖', 'probability' => 22, 'amount' => 10], ['id' => 6, 'prize' => '谢谢参与', 'probability' => 50, 'amount' => 10], ]; for ($i = 0; $i < 10000; $i++) { $res[] = getRandPrize($arrPrize); } $res2 = array_count_values($res); ksort($res2); foreach ($res2 as $key => $val) { $res3[$key]['count'] = $val; $res3[$key]['probability'] = $val / count($res) * 100; } print_r($res3);
模拟10000次的一个结果
array( array( 'count' => 103, 'probability' => 1.03, ), array( 'count' => 510, 'probability' => 5.1, ), array( 'count' => 981, 'probability' => 9.81, ), array( 'count' => 1211, 'probability' => 12.11, ), array( 'count' => 2155, 'probability' => 21.55, ), array( 'count' => 5040, 'probability' => 50.4, ), );