<?php
$gender = array(
'Male'=>30,
'Female'=>50,
'U' =>20);
$total = array_sum(array_values($gender));
$current = 0;
$rand = rand(1,$total);
foreach ($gender as $key=>$value)
{
$current += $value;
if ($current > $rand)
{
echo $key;
break;
}
}
?>
目前我正在尝试根据加权百分比生成随机值。在这个例子中,男性有30%的几率,50女性和20%的几率。我有一种感觉,代码中的逻辑是错误的,所以我运行了100次脚本,通常你会得到30个男性,但事实并非如此。有更聪明的方法吗?
答案 0 :(得分:2)
逻辑基本上是正确的,但您应该使用>=
作为比较运算符。要知道为什么这是正确的,假设你有两个概率相同的选择:
$gender = array('Male' => 1, 'Female' => 1);
$rand
将是1
或2
。如果$rand
为1
,您可能会选择Male
。您的代码将测试1 > 1
并且它将失败,正确的测试将是1 >= 1
,这将成功。
此外,您应该进行100多次测试以验证随机算法。 1,000可能会产生更具代表性的结果。
答案 1 :(得分:1)
你说的是正确的。在另一个StackOverflow回答here中详细说明了这个详细算法。
您的实施可能如下所示:
function getWeightedRandom(array $options) {
// calculate the total of all weights
$combined = array_sum($options);
// generate a random number, where 0 <= $random < $combined
$random = rand(0, $combined - 1);
// keep subtracting weights until we drop below an option's weight
foreach($options as $name => $weight) {
if($random < $weight) {
return $name;
}
$random -= $weight;
}
}
// the weights to use for our trials (do not have to add up to 100)
$gender = array(
'Male' => 30,
'Female' => 50,
'U' => 20);
// used for keeping track of how many of each result
$results = array(
'Male' => 0,
'Female' => 0,
'U' => 0);
// run a large number of trials to properly test our accuracy
for($i = 0; $i < 100000; $i++) {
$result = getWeightedRandom($gender);
$results[$result]++;
}
print_r($results);
输出:
Array
(
[Male] => 30013
[Female] => 49805
[U] => 20182
)
对我来说很好看!
答案 2 :(得分:0)
试试这个:
/**
* random by rates
* @param int $rates
* @param int $pow Decimal digits
*/
function randombyrates($rates,$pow){
$much = pow(10, $pow);
$max = array_sum($rates) * $much;
$rand = mt_rand(1, $max);
$base = 0;
foreach ($rates as $k => $v) {
$min = $base * $much + 1;
$max = ($base + $v) * $much;
if ($min <= $rand && $rand <= $max) {
return $k;
} else {
$base += $v;
}
}
return false;
}
$gender = array(
'Male'=>30,
'Female'=>50,
'U' =>20);
echo randombyrates($gender);
祝你好运!