随机数,但有偏见

时间:2011-04-18 07:07:04

标签: php random

如何创建一个偏差在数字范围内的随机数生成器? 说我有这个:

$rnum = rand(0,200);

所以$rnum == 3以及下次$rnum == 106然后$rnum == 10等等......

但我宁愿偏差范围为80-120,因此更有可能在偏差范围内选择一个数字而不是在它之外。

$rnum == 86,下次$rnum == 112然后$rnum == 93,但仍然可以$rnum == 24等等......

我以为我可以做到这一点:

if($rnum < $middle_of_bias){
    $rnum++;
}else{
    $rnum--;
}

但是没有真正起作用,因为你可以看到$rnum == 1在应用偏见之后它只会使2不能使这种方法非常成功。

感谢您的帮助。

编辑:每个人的答案都很棒。我真的很喜欢 gnur的一个和 Phil H's 我已经对 rmflow的进行了修改,它正在按照我想要的方式工作。 感谢每一位帮助过的人!

if (rand(0, 10) > 2)
{
    $rnum = rand($low, $high);
}else{
    $rnum = rand(0, $max);
}

7 个答案:

答案 0 :(得分:10)

if (rand(0, 10) > 7)
{
    $rnum = rand(80, 120);
}
else
{
    $rnum = rand(0, 200);
}

答案 1 :(得分:1)

您可能希望使用rand()从统一分布中的较大范围获取随机数,然后使用函数将较大范围映射到您实际想要的较小范围,从而产生分布你想要的。

答案 2 :(得分:1)

偏向随机数的另一种可能性:

$rnum = rand(90,110);
$rex1 = 45 - rand(0,90);
$rex2 = 45 - rand(0,90);
$rbias = $rnum + $rex1 + rex2;

这将增加100左右的数字的可能性,0-10和190-200的数字是非常不可能的,而80-120之间的数字很可能。

答案 3 :(得分:0)

只需将额外容量添加到范围的末尾,并将超出最大值的任何内容转移到偏差范围内。

$rnum = rand(0,240);
if($rnum > 200) {
    $rnum -= 120; // 201 -> 81
}

这只会使获得该范围内的值的概率加倍。如果您想要更多偏见,请进一步扩展范围:

$rmax = 200;
$bmin = 80;
$bmax = 120;
$brange = $bmax - $bmin;
$nbias = 4;
$rnum = rand(0,$rmax+($brange*$nbias));
if($rnum > $rmax) {
    $excess -= $rmax; // 201 -> 81
    $remainder  = modulo($rnum,$brange);
    $rnum = $remainder+$bmin;
}

答案 4 :(得分:0)

创建两个范围,一个有偏,一个没有。

not biased range: 0, 200
biased range:     80, 120
然后选择一个没有偏见的数字的可能性,比如说20%。那是第5个,或者是5个中的1个,然后生成1到5之间的随机数,如果它是1,则从无偏差范围生成一个随机数。否则从偏差范围产生一个数字。

自从我开始写作以来,已经有了几个答案。来自rmflow的答案描述了我的流程,但是获得无偏差数字的可能性为36%。

祝你好运! :)

答案 5 :(得分:0)

您可以通过定义$ item =&gt; $ weight:

的数组来实现
$biasedArray = array(
  'Blue'   => 50,
  'Yellow' => 30,
  'Pink'   => 10,
  'Green'  => 10,
);

chooseFromBiasedArray($biasArray);

function chooseFromBiasedArray($biasArray) {
  $totalWeight = array_sum($biasedArray);
  $randChoice = rand(1,$totalWeight);

  $currentWeight = 0;
  reset($biasedArray);
  while ($currentWeight < $randChoice) {
    $currentKey = key($biasedArray);

    $currentWeight += $biasedArray[$currentKey];
    if ($currentWeight < $randChoice) {
      next($biasedArray);
    }
  }

  //echo $randChoice . " -> " . current($biasArray);
  return current($biasArray);
}

我写得非常快,你可以做得更干净但想法也一样。

答案 6 :(得分:0)

@rmflow的答案将是我将加权偏差添加到范围的方式。但是,我将使用mt_rand函数以获得更好的随机性。

mt_rand-通过Mersenne Twister随机数生成器生成随机值。

据称它也快了4倍(This function produces a better random value, and is 4 times faster than rand()),但是根据我的经验,我发现性能几乎没有提高20%。

if (mt_rand(0, 10) > 7)
{
    $rnum = mt_rand(80, 120);
}
else
{
    $rnum = mt_rand(0, 200);
}