随机生成中的逻辑

时间:2013-09-13 01:01:49

标签: php arrays

<?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个男性,但事实并非如此。有更聪明的方法吗?

3 个答案:

答案 0 :(得分:2)

逻辑基本上是正确的,但您应该使用>=作为比较运算符。要知道为什么这是正确的,假设你有两个概率相同的选择:

$gender = array('Male' => 1, 'Female' => 1);

$rand将是12。如果$rand1,您可能会选择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);
祝你好运!