我在论坛上对此有很多不满,但所有答案都是如此具体的问题。我发现的最近的一个是:Probability Random Number Generator by Alon Gubkin。
不同之处在于,Alon要求给予一张脸(这是六张)额外的机会。在我的情况下,我想划分六个面孔的机会,使它们加起来达到100%。例如,面部1有40%的几率,面部2只有10%,面部3有25%,......等。
我该怎么做?
答案 0 :(得分:8)
具有线性概率的单概率检查可以通过以下方式轻松完成:
function checkWithProbability($probability=0.1, $length=10000)
{
$test = mt_rand(1, $length);
return $test<=$probability*$length;
}
例如,这将产生:
for($i=0; $i<10; $i++)
{
var_dump(checkWithProbability(1/3));
}
类似的东西:
bool(false) bool(true) bool(false) bool(false) bool(false) bool(false) bool(false) bool(false) bool(true) bool(false)
您可以使用该原则以期望的概率检查您的边缘:
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
}
这个想法是使用geometry probability - 即将一些行部分拆分成具有相应长度的部分,然后检查我们的随机数属于哪个部分。
0.75 0.9 | | V V *--------*--*-----*-*--*--* <-- (length) ^ ^ ^ ^ ^ | | | | | 0 0.4 0.5 0.8 1
示例将是:
$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));
}
结果如:
int(1) int(2) int(2) int(6) int(3) int(1) int(1) int(6) int(1) int(1)
你可以增加$length
- 从理论上讲,这会增加随机检查的“质量”,但这并不是一件容易的事 - 因为mt_rand()
使用伪随机生成器,Mersenne Twister(并且在理想情况下,这不是真正的线性概率)
答案 1 :(得分:2)
一个非常简单的方法是使用长度为100的数组,在其中编写“面”数字,将其洗牌并获得第一个元素。
因此,对于您在该阵列中的示例是40x1,10x2,25x3。
小代码示例(未经测试):
$probabilities = array(
1 => 40,
2 => 10,
3 => 25,
4 => 5,
5 => 10,
6 => 10
);
$random = array();
foreach($probabilities as $key => $value) {
for($i = 0; $i < $value; $i++) {
$random[] = $key;
}
}
shuffle($random);
echo $random[0];
答案 2 :(得分:1)
在您的情况下,您可能会生成从1到100的随机,然后:
if random in 1:40 -> face 1
elseif random in 41:50 -> face 2
and so on.
当然,实际代码实现范围会更复杂,而不是硬编码ifs
答案 3 :(得分:0)
我可以想到一个非常简单的解决方案。这个不会改变随机数生成器的生成模式,但会解释结果以适应您上面的问题。我要求随机数生成器生成0到9之间的数字。然后执行以下映射,我根据分配给该值的概率将生成的数字的范围分配给我的intrest的值:
If result <= 3, face=1
else if result <=5, face =2
else is result <=25 face =3
//and so on