【问题标题】:Returning a random value from array with probability proportional to it's value从数组中返回一个随机值,其概率与它的值成正比
【发布时间】:2012-01-07 00:10:29
【问题描述】:

我有一个类似的数组

$keywords = array('apple'=>10,'orange'=>2,'grape'=>12); 

我想从数组中随机选择一个“密钥”。然而,概率分布应该使得选择一个元素的概率应该与它的值成正比。

【问题讨论】:

    标签: php arrays random probability


    【解决方案1】:

    我会这样做:

        $probabilities = array('apple'=>50, 'orange'=>20, 'banana'=>10);
    
        function random_probability($probabilities) {
          $rand = rand(0, array_sum($probabilities));
          do {
            $sum = array_sum($probabilities);
            if($rand <= $sum && $rand >= $sum - end($probabilities)) {
              return key($probabilities);
            }
          } while(array_pop($probabilities));
        }
    

    【讨论】:

      【解决方案2】:

      O(log(n)) 方法(直接从answer to a very similar question 中提取):

      通常的技术是将数组转换为累积和的数组:

       [10 60 5 25]  --> [10 70 75 100]
      

      在从零到累计总数的范围内选择一个随机数(在示例中:0 &lt;= x &lt; 100)。然后,在累积数组上使用bisection,将索引定位到原始数组中:

      Random variable x      Index in the Cumulative Array      Value in Original Array
      -----------------      -----------------------------      ----------------------
       0 <= x < 10                      0                            10
      10 <= x < 70                      1                            60
      70 <= x < 75                      2                             5
      75 <= x < 100                     3                            25 
      

      例如,如果随机变量 x 为 4,则将累积数组二等分得到位置索引 0,对应于原始数组中的 10。

      并且,如果随机变量 x 为 72,则将累积数组二等分得到位置索引 2,对应于原始数组中的 5。

      【讨论】:

        【解决方案3】:

        将所有值相加(10+2+12 为 24);取一个 [0, 24) 范围内的随机数,根据该数字是在 [0, 10)、[10, 12) 还是 [12, 24) 范围内选择对应的元素。

        【讨论】:

        • 这就是我所做的。一种愚蠢的方法可能是创建一个数组,其中添加了 10 次“苹果”,添加了 2 次“橙色”,依此类推,然后使用 array_rand 随机选择一个元素
        • 哈哈,不错。好吧,在数学上也是一样,但诀窍是以最有效的方式对其进行编程:-)
        • 如果您要选择许多随机值,那么 Akshar 的算法效率更高。 Akshar 在 O(1) 中,而 Kerrek 在 O(log(n)) 中。
        猜你喜欢
        • 2013-05-05
        • 2020-01-13
        • 1970-01-01
        • 1970-01-01
        • 2013-03-22
        • 2023-03-09
        • 2016-04-29
        • 1970-01-01
        • 2019-09-21
        相关资源
        最近更新 更多