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);
}