Generate random numbers with fix probability

php, probability, random

Solution

The single probability check with linear probability can be easily done with:

function checkWithProbability($probability=0.1, $length=10000)
{
   $test = mt_rand(1, $length);
   return $test<=$probability*$length;
}

For example, this will produce:

for($i=0; $i<10; $i++)
{
   var_dump(checkWithProbability(1/3));
}

Something like:

bool(false)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(true)
bool(false)

And you can use that principle to get your edges check with desired probability:

function checkWithSet(array $set, $length=10000)
{
   $left = 0;
   foreach($set as $num=>$right)
   {
      $set[$num] = $left + $right*$length;
      $left = $set[$num];
   }
   $test = mt_rand(1, $length);
   $left = 1;
   foreach($set as $num=>$right)
   {
      if($test>=$left && $test<=$right)
      {
         return $num;
      }
      $left = $right;
   }
   return null;//debug, no event realized
}

The idea is to use geometry probability - i.e. split some line part into pieces with corresponding length and then check to which part our random number belongs.

                 0.75  0.9
                  |    |
                  V    V
*--------*--*-----*-*--*--* <-- (length)
^        ^  ^       ^     ^
|        |  |       |     |
0      0.4 0.5     0.8    1

Sample will be:

$set = [
  1 => 0.4,
  2 => 0.1,
  3 => 0.25,
  4 => 0.05,
  5 => 0.1,
  6 => 0.1
];
for($i=0; $i<10; $i++)
{
   var_dump(checkWithSet($set));
}

With result like:

int(1)
int(2)
int(2)
int(6)
int(3)
int(1)
int(1)
int(6)
int(1)
int(1)

You can increase `$length` - in theory, this will increase "quality" of randomize check, but that's not too easy thing - because `mt_rand()` uses pseudo-random generator, Mersenne Twister (and in ideal case that's not true linear probability)

Problem

I red a lot in the forum about this, but all answers were so specific to the the asked question. The nearest one I found to my need was:Probability Random Number Generator by Alon Gubkin. The difference is that, Alon ask to give a one face (which is six) extra chance. In my case, I want to divide the chance for the six faces so that they add up to 100%. For example, face 1 has chance of 40%, face 2 has only 10%, face 3 has 25%, ... etc. How can I do that?

Original source

Related problems