Php 随机数,但有偏差

Php 随机数,但有偏差,php,random,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 = 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 = 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;
}

您可能希望使用
rand()
从均匀分布的较大范围中获取随机数,然后使用函数将较大范围映射到实际需要的较小范围,从而生成所需的分布。

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

not biased range: 0, 200
biased range:     80, 120
然后选择一个无偏数字的似然度,比如20%。这是五分之一,或者说五分之一。然后生成一个介于1和5之间的随机数,如果结果为1,则从无偏差范围生成一个随机数。否则,从偏置范围生成一个数字

$rnum = rand(0,240);
if($rnum > 200) {
    $rnum -= 120; // 201 -> 81
}
自从我开始写作以来,我得到了一些答案。rmflow的答案描述了我的流程,但有36%的可能性得到一个无偏差的数字


祝你好运!:)

另一种使随机数产生偏差的可能性:

$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之间的数字很可能出现

您可以通过定义$item=>$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);
}
$biasedArray=阵列(
“蓝色”=>50,
“黄色”=>30,
“粉红”=>10,
“绿色”=>10,
);
从biaseray($biasArray)中选择;
函数从biaseray($biasArray)中选择{
$totalWeight=数组和($biasedArray);
$randChoice=rand(1,$totalWeight);
$currentWeight=0;
重置($biasedArray);
而($currentWeight<$randChoice){
$currentKey=key($biasedArray);
$currentWeight+=$biasedArray[$currentKey];
如果($currentWeight<$randChoice){
其次($biasedArray);
}
}
//echo$randChoice.“->.”当前($biasArray);
返回电流($biasArray);
}

我写得很快,你可以做得更干净,但想法是一样的。

由@rmflow给出的答案是我将加权偏差添加到范围中的方式。然而,我会使用mt_rand函数来获得更好的随机性

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

据说它的速度也提高了4倍(),但是,根据我的经验,性能几乎没有提高,只有20%

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

你想要多少偏差?为什么选择rand(0,10)>7?这意味着11次中有3次总是在偏差范围内。剩下的8次有20%的机会达到偏差范围(1.6次),因此11次中有4.6次在偏差范围内。因此,实际上,偏差范围的命中率要低于偏差范围之外的命中率。@hugo,但每个数字的命中率会更高,因为只有20%的数字在41%的时间内被命中。@gnur正确,命中它们的概率比任何其他数字都大,但我从问题中了解到的是,他希望命中偏差范围内的一个数字,概率高于50%。要创建以100为中心的正态分布,可以使用如下等式:
100+(200*rand()-100)
,其中平均值为100,方差为200。
if (mt_rand(0, 10) > 7)
{
    $rnum = mt_rand(80, 120);
}
else
{
    $rnum = mt_rand(0, 200);
}