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?
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)