【问题标题】:Random numbers with non-uniform discrete densities具有非均匀离散密度的随机数
【发布时间】:2011-10-31 15:36:02
【问题描述】:

只是想知道这是什么类型的算法,
或者如果有更简单/更有效的方法来解决这个问题:

假设我们有一定的概率密度,比如说

prob[] = {.1, .15, .25, .05, .45}

第 1 组 - 10%
第 2 组 - 15%
第 3 组 - 25%
第 4 组 - 5%
第 5 组 - 45%

和一个随机数,(0,1),
跑 = .853234

插入 5 个组之一

if (ran <=prob[0]) selection = 1;  
else if (ran <= prob[0]+prob[1]) selection = 2;  
...
else if (ran <= prob[0]+prob[1]+...+prob[4]) selection = 5;  

我对随机数生成不是很精通

【问题讨论】:

    标签: random non-uniform-distribution


    【解决方案1】:

    您在这里所做的基本上是反转cumulative distribution function。设F为随机变量X在给定分布下的CDF,则定义为F(x) == P[X &lt;= x]

    这里非常有用的是,如果你生成一个介于0和1之间的均匀随机变量U,那么

    P[F^-1(U) <= x] == P[U <= F(x)] == F(x) == P[X <= x]
    

    这意味着F^-1(U) 将与X 具有相同的分布!

    当然,这只有在您可以反转 CDF 时才有可能,但在您的情况下,F 是一个分段函数(如楼梯),并且您的算法确定,对于给定的统一值,该值在哪一步遇见了。因此,您的算法是完全正确的。

    但是,如果您要生成大量随机数,则可以改进它:首先生成 CDF 表,在您的情况下是

    CDF[] = {.1, .25, .5, .55, 1.}
    

    那么对于每个生成的介于 0 和 1 之间的统一数,只需对 CDF 表进行二分法即可检索到对应的索引。

    【讨论】:

      【解决方案2】:

      你的算法是正确的。但是,在您的示例中,概率加起来不等于 1。

      【讨论】:

        【解决方案3】:

        除了你的概率加起来不是 100% 之外,该代码将起作用(因此没有一个 if 语句可能匹配)。

        通过使用累积概率分布可以稍微简化该方法:

        cumprob[5] = {.1, .2, .45, .50, 1.0};
        

        这也可以让您用lsearch 代替 if-elif 链。

        【讨论】:

          【解决方案4】:

          您的算法将随机浮点数用于离散分布,这不是实现这一点的最佳方式。您的实现可能会提供与给定分布几乎无法区分的分布,但它在科学上并不正确。

          相反,找到给定概率的最小公分母(在您的示例中为 5%)并使用 [0,19] 中的随机整数来选择您的组。示例:

          switch(random(19)) {
          case 0:
          case 1:
            selection = 1;
            break;
          case 2:
          case 3:
          case 4:
            selection = 2;
            break;
          case 5:
          case 6:
          case 7:
          case 8:
          case 9:
            selection = 3;
            break;
          case 10:
            selection = 4;
            break;
          case 11:
          case 12:
          case 13:
          case 14:
          case 15:
          case 16:
          case 17:
          case 18:
          case 19:
            selection = 4;
            break;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-08-23
            • 1970-01-01
            • 2017-07-16
            • 2014-02-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多