【问题标题】:generate a random number between 1 and x where a lower number is more likely than a higher one生成一个介于 1 和 x 之间的随机数,其中较小的数字比较大的数字更有可能
【发布时间】:2011-03-19 01:48:09
【问题描述】:

这更像是一个数学/一般编程问题,但我用 PHP 编程是有区别的。

我认为最简单的解释方法是举个例子。

如果范围在 1 到 10 之间。

我想生成一个介于 1 到 10 之间但更可能低于高的数字。

我能想到的唯一方法是生成一个数组,其中 10 个元素等于 1,9 个元素等于 2,8 个元素等于 3.....1 个元素等于 10。然后根据元素的数量。

问题是我可能要处理 1 - 100000 并且该数组会大得离谱。

那么如何做到最好呢?

【问题讨论】:

  • 不,它不会破坏目的。他只是想将均匀密度映射到另一个分布,这在蒙特卡洛应用中很常见。 @OP:能否请您提供一个分发功能?
  • @Woot:你对“随机”的理解是什么?随机变量具有分布函数。而且分布很少是线性的。
  • 不过,他并没有“强迫”任何一个结果。他只是比其他人更有可能获得某些结果。可以这样想:我有一个袋子,里面有 15 张卡片。五张卡片上写着“1”,四张写着“2”,三张写着“3”,两张写着“4”,一张写着“5”。我从袋子里随机抽一张牌。结果仍然是随机的,但我得到 1(低数字)的可能性是得到 5(高数字)的可能性的五倍。我没有强求任何结果,但我确实将随机结果更偏向于低数字。
  • 或者只是掷一对骰子。您获得 7(概率 6/36)的可能性是获得 1 或 12(概率 1/36)的 6 倍,但是对于多个应用程序,这被认为是随机的。 :-)
  • 掷两个骰子不是不可能得到1吗?

标签: php math random


【解决方案1】:

生成一个介于 1 和 foo(n) 之间的数字,其中 foo 在 n 上运行算法(例如,对数函数)。然后在结果上反转 foo()。

【讨论】:

    【解决方案2】:

    生成数字n,即0 <= n < 1,将其乘以自身,而不是乘以x,在其上运行地板并加1。抱歉,我很久以前使用php在其中编写代码

    【讨论】:

    • @Zano,因为他正在对一个小于 1 的数进行平方,即范围下端的数组
    • @murgatroid99:当然,我没有注意自我注意:评论SO答案时不要和宝宝玩
    【解决方案3】:

    你可以这样做

    $rand = floor(100000 * (rand(0, 1)*rand(0, 1)));
    

    或者类似的东西

    【讨论】:

      【解决方案4】:

      您需要做的是在更大的间隔(最好是浮点数)内生成一个随机数,并以非均匀的方式将其映射到 [1,10] 中。确切的方式取决于如何您希望 1 比 9 或 10 更有可能。

      有关 C 语言解决方案,请参阅these libraries。您可能会发现this in PHP 的用途。

      【讨论】:

        【解决方案5】:

        生成一个介于 0 和一个随机数之间的随机数!

        【讨论】:

        • 但是效率低下。它需要生成两个随机数;)
        • @nikic:您在 1 到 n 中生成了两次随机数,这意味着 2log(n) 位的随机性。对于问题中的分布,这是最优的,因为 2log(n) = log(n^2)。
        • 这确实给出了下降的概率,但它与问题中提出的算法生成的不同。相反,它给出了 sum(1/i:n)/n 的概率,其中 n 是最大值,i 是所讨论的整数。
        • a.imageshack.us/img710/8336/rndrnd.png 中输出图形(密度)......对于不忠的人:D
        【解决方案6】:

        基本上有两种(或更多?)方法可以将均匀密度映射到任何分布函数:Inverse transformation samplingRejection sampling。我认为在你的情况下你应该使用前者。

        【讨论】:

          【解决方案7】:

          一般来说,您似乎想从Poisson distribution 而不是[均匀分布](http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)) 中抽取一个随机数。在上面引用的 wiki 页面上,有一个部分专门说明了如何使用生成伪泊松分布的连续分布...check it out。请注意,您可能需要测试不同的 λ 值以确保分布按您的意愿工作。

          【讨论】:

            【解决方案8】:

            快速简单:

            rand(1, rand(1, n))
            

            【讨论】:

            • 这是一个很好的简单解决方案...但我发现它有时会导致 0。它应该是 rand(1,rand(1,n)。谢谢 :)
            【解决方案9】:

            这取决于你想要的确切分布,即应该以什么概率出现什么数字。

            例如,对于偶数 n,您可以执行以下操作:生成一个介于 1 和 n/2 之间的整数随机数 x,并生成第二个介于 1 和 n+1 之间的数字。如果 y > x 则生成 x,否则生成 n-x+1。这应该为您提供示例中的分布。

            【讨论】:

              【解决方案10】:

              我认为这应该给出请求的分布:

              在 1 .. x 范围内生成一个随机数。在 1 .. x+1 范围内生成另一个。 返回两者中的最小值。

              【讨论】:

                【解决方案11】:

                让我们考虑一下您的数组想法如何改变概率。通常,从 1 到 n 的每个元素都有 1/n 的概率,因此概率相同。

                由于您有 n 个 1 条目,n-1 个条目 2...1 个 n 条目,那么您拥有的条目总数是一个算术级数。从 1 到 n 的算术级数之和为 n(1+n)/2。所以现在我们知道每个元素的概率都应该用它作为分母。

                元素 1 有 n 个条目,所以它的概率是 n/n(1+n)/2。元素 2 是 n-1/n(1+n)/2 ... n 是 1/n(1+n)/2。这给出了分子的一般公式为 n+1 -i,其中 i 是您正在检查的数字。这意味着我们现在有一个函数来表示任何元素的概率为 n-i+1/n(1+n)/2。根据定义,所有概率都在 0 和 1 之间,总和为 1,这是下一步的关键。

                我们如何使用这个函数来调整元素出现的次数?使用连续分布(即双精度而不是整数)更容易,但我们可以做到。首先,让我们创建一个概率数组,将其命名为 c,然后对它们进行运行求和(cumsum)并将其存储回 c。如果这没有意义,它只是像

                这样的循环
                
                for(j=0; j < n-1; j++)
                   if(j) c[j]+=c[j-1]
                

                现在我们有了这个累积分布,生成一个从 0 到 1 的数字 i(一个 double,而不是 int。我们可以检查 i 是否在 0 和 c[0] 之间,返回 1。如果 i 在 c[ 1] 和 c[2] 返回 2...一直到 neg

                for(j=0; j < n=1;j++)
                   if(i %lt;= c[j]) return i+1
                

                这将根据您计算的概率分配整数。

                【讨论】:

                  【解决方案12】:
                  <?php 
                  //get random number between 1 and 10,000
                  $random = mt_rand(1, 10000); 
                  ?>
                  

                  【讨论】:

                  • 虽然这会返回一个随机数,但它实际上并没有回答 OP 的问题。
                  猜你喜欢
                  • 2012-11-25
                  • 2012-11-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-12-06
                  • 1970-01-01
                  • 2021-09-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多