【问题标题】:Generate random numbers with fix probability生成具有固定概率的随机数
【发布时间】:2014-02-05 08:46:00
【问题描述】:

我在论坛中对此进行了很多讨论,但所有答案都针对所提出的问题非常具体。我发现最接近我需要的是:Probability Random Number Generator by Alon Gubkin

不同的是,Alon 要求给一个人脸(也就是六个人)额外的机会。就我而言,我想划分六个面的机会,使它们加起来为 100%。例如,面 1 有 40% 的机会,面 2 只有 10%,面 3 有 25%,......等等。

我该怎么做?

【问题讨论】:

标签: php random probability


【解决方案1】:

线性概率的单一概率检查可以通过以下方式轻松完成:

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

类似:

布尔(假) 布尔(真) 布尔(假) 布尔(假) 布尔(假) 布尔(假) 布尔(假) 布尔(假) 布尔(真) 布尔(假)

您可以使用该原理以期望的概率进行边缘检查:

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 | | 五五 *--------*--*-----*-*--*--*

样本将是:

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

结果如下:

整数(1) 整数(2) 整数(2) 整数(6) 整数(3) 整数(1) 整数(1) 整数(6) 整数(1) 整数(1)

您可以增加$length - 从理论上讲,这将提高随机检查的“质量”,但这并不是一件容易的事情 - 因为mt_rand() 使用伪随机生成器Mersenne Twister(在理想情况下不是真正的线性概率)

【讨论】:

  • 这真的让我的朋友感到高兴。这就是我一直在寻找的。非常感谢你^^。
【解决方案2】:

一个非常简单的方法是创建一个长度为 100 的数组,在其中写入您的“面孔”数字,将其打乱并获取第一个元素。

因此,对于您的示例,该数组中的值是 40x 1、10x 2、25x 3。

小代码示例(未测试):

$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];

【讨论】:

    【解决方案3】:

    在您的情况下,您可能会生成从 1 到 100 的随机数,然后:

    if random in 1:40 -> face 1
    elseif random in 41:50 -> face 2
    and so on. 
    

    当然,真正的代码要获得真正的范围而不是硬编码的 ifs 会稍微复杂一些

    【讨论】:

      【解决方案4】:

      我能想到一个非常简单的解决方案。这不会改变随机数生成器的生成模式,但会解释结果以适合您的上述问题。我会要求随机数生成器生成 0 到 9 之间的数字。然后执行以下映射,根据我分配给该值的概率,我将生成的数字范围分配给我的兴趣值:

      If result <= 3, face=1
      else if result <=5, face =2
      else is result <=25 face =3
      //and so on
      

      【讨论】:

        猜你喜欢
        • 2012-12-04
        • 2012-02-11
        • 1970-01-01
        • 2011-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多