Random number but with a bias
How would I go about creating a random number generator which has a bias to be within a range of numbers? say I have this:
$rnum = rand(0,200);
so $rnum == 3
and next time $rnum == 106
then $rnum == 10
and so on...
But I would rather have a bias range of say 80 - 120 so it would more likely select a number within the bias range than 开发者_高级运维outside of it.
$rnum == 86
and next time $rnum == 112
then $rnum == 93
but still be able to $rnum == 24
and so on...
I thought I might have been able to do this:
if($rnum < $middle_of_bias){
$rnum++;
}else{
$rnum--;
}
but didn't really work, as you can see if $rnum == 1
after applying the bias it would only make it 2
not making this method very successful.
Thanks for your help.
Edit: everyones answers were great. I really liked gnur's one and Phil H's I have made my modifications to rmflow's one and it is working how I wanted it to. Thanks to every one that helped!
if (rand(0, 10) > 2)
{
$rnum = rand($low, $high);
}else{
$rnum = rand(0, $max);
}
if (rand(0, 10) > 7)
{
$rnum = rand(80, 120);
}
else
{
$rnum = rand(0, 200);
}
You probably want to use rand()
to get a random number from a larger range in a uniform distribution and then use a function to map that larger range to the smaller range you actually want in a way that produces the distribution you want.
Another possibility to bias your random number:
$rnum = rand(90,110);
$rex1 = 45 - rand(0,90);
$rex2 = 45 - rand(0,90);
$rbias = $rnum + $rex1 + rex2;
This will increase likeliness of numbers around 100, numbers of 0-10 and 190-200 are quite unlikely while numbers between 80-120 are very likely.
create two ranges, one biased, one not.
not biased range: 0, 200
biased range: 80, 120
then pick a likeliness for getting a none biased number, say 20%. that's one 5th, or, 1 out of 5. then generate a random number between 1 and 5, if it comes out as 1, generate a random number from the none biased range. otherwise generate a number from the biased range.
since i started writing, a couple of answers has come in. the answer from rmflow describes my flow, but with a 36% likeliness of getting a none biased number.
good luck! :)
Just add spare capacity to the end of the range and anything above the maximum you shift into the biased range.
$rnum = rand(0,240);
if($rnum > 200) {
$rnum -= 120; // 201 -> 81
}
This will only double the probability of getting a value in that range. If you want more bias, extend the range further:
$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;
}
You can do it by defining an array of $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);
}
I wrote it very fast, you can do it much cleaner but the idea will be the same.
The answer by @rmflow would be the way in which I would add a weighted bias to a range. However, I would use the mt_rand function for better randomness.
mt_rand — Generate a random value via the Mersenne Twister Random Number Generator.
It is also purported to be 4x faster (This function produces a better random value, and is 4 times faster than rand()), however, in my experience I see little only a 20% increase in performance.
if (mt_rand(0, 10) > 7)
{
$rnum = mt_rand(80, 120);
}
else
{
$rnum = mt_rand(0, 200);
}
精彩评论