抽奖概率
大约 2 分钟
方法 get_rand()
是网上流传的写法,我一直不能理解为什么要这么写。数学有点菜,见笑。 但是按照朴素逻辑考虑,一次抽奖就是在好多的球球里面抽一个。那么随机一个数,去这么多数字里面 找对应的奖就对了。所以我的方法就是 get_rand1()
。
$arr['a'] = 0;
$arr['b'] = 1;
$arr[1] = 18;
$arr[2] = 20;
$arr[3] = 15;
$arr[4] = 20;
$arr[5] = 20;
$arr[6] = 13;
var_export($arr);
echo '<br>';
function get_rand($proArr) {
$result = '';
//概率数组的总概率精度
$proSum = array_sum($proArr);
//概率数组循环
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum); //返回随机整数
if ($randNum <= $proCur) {
$result = $key;
break;
} else {
$proSum -= $proCur;
}
}
unset ($proArr);
return $result;
}
function get_rand1($proArr) {
$result = '';
$proSum = array_sum($proArr); //概率数组的总概率空间
$randNum = mt_rand(1, $proSum); //返回随机概率空间
$tmpNum = 0; //当前值所在概率空间
//概率数组循环
foreach ($proArr as $key => $proCur) {
$tmpNum += $proCur;
if ($randNum <= $tmpNum) {
$result = $key;
break;
}
}
return $result;
}
$times = 10000*1000;
$res = [];
$t1 = microtime(true);
for($i=1;$i<$times;$i++){
$key = get_rand($arr);
if(isset($res[$key])){
$res[$key]++;
}else{
$res[$key] = 1;
}
}
$t0 = microtime(true) - $t1;
ksort($res);
echo $t0,'<br>';
var_export($res);
echo '<br>';
$res = [];
$t1 = microtime(true);
for($i=1;$i<$times;$i++){
$key = get_rand1($arr);
if(isset($res[$key])){
$res[$key]++;
}else{
$res[$key] = 1;
}
}
$t0 = microtime(true) - $t1;
ksort($res);
echo $t0,'<br>';
var_export($res);
下面是 千万次测试 的结果
概率数组
array ( 'a' => 0, 'b' => 1, 1 => 18, 2 => 20, 3 => 15, 4 => 20, 5 => 20, 6 => 13, )
方法 get_rand()
的结果
4.2199540138245
array ( 'b' => 93181, 1 => 1680848, 2 => 1871257, 3 => 1400675, 4 => 1870170, 5 => 1869457, 6 => 1214411, )
方法 get_rand1()
的结果
2.9911849498749
array ( 'b' => 93549, 1 => 1683817, 2 => 1868176, 3 => 1402612, 4 => 1868520, 5 => 1867259, 6 => 1216066, )
令我比较意外的是,虽然我的方法快了近30%,但是为什么两个方法的结果基本接近。
以上