获得总和为M的N个随机数

我想得到N个随机数,他们的总和是一个值。

例如,假设我想要5个随机数,它们的和为1

那么有效的可能性是:

0.2 0.2 0.2 0.2 0.2 

其他可能性是:

 0.8 0.1 0.03 0.03 0.04 

等等。 我需要这个来创build模糊C-均值的所有物matrix。

只要生成N个随机数,计算它们的总和,然后每个数除以总和。

生成0到1之间的N-1个随机数,将数字0和1本身加到列表中,对它们进行sorting,并取相邻数字的差值。

我认为值得注意的是,目前接受的答案并不是一个统一的分布:

“只要生成N个随机数,计算它们的总和,每个数除以总和”

为了看这个,我们来看一下N = 2和M = 1的情况。 这是一个微不足道的情况,因为我们可以通过在范围(0,1)中均匀地selectx来生成一个列表[x,1-x]。 所提出的解决scheme生成一个对[x /(x + y),y /(x + y)],其中x和y在(0,1)中是均匀的。 为了分析这个,我们select一些z使得0 <z <0.5并且计算第一个元素小于z的概率。 如果分配是统一的,则这个概率应该是z。 但是,我们得到

Prob(x(x + y)<z)= Prob(x <z(x + y))= Prob(x(1-z)<zy)= Prob ))= z /(2-2z)。

我做了一些快速的计算,似乎到目前为止唯一的解决scheme,可以导致一个统一的分配由Matti Virkkunen提出 :

“生成0到1之间的N-1个随机数字,将数字0和1本身添加到列表中,对它们进行sorting,并取相邻数字的差异。

在Java中:

 private static double[] randSum(int n, double m) { Random rand = new Random(); double randNums[] = new double[n], sum = 0; for (int i = 0; i < randNums.length; i++) { randNums[i] = rand.nextDouble(); sum += randNums[i]; } for (int i = 0; i < randNums.length; i++) { randNums[i] /= sum * m; } return randNums; } 
  1. 生成N-1个随机数字。
  2. 计算所述数字的总和。
  3. 将计算的总和与期望的总和之间的差值添加到集合中。

你现在有N个随机数,他们的总和就是所需的总和。

只要生成N个随机数,计算它们的总和,然后每个数除以总和。

按照Guillaume公认的答案进行扩展 ,下面是一个Java函数。

 public static double[] getRandDistArray(int n, double m) { double randArray[] = new double[n]; double sum = 0; // Generate n random numbers for (int i = 0; i < randArray.length; i++) { randArray[i] = Math.random(); sum += randArray[i]; } // Normalize sum to m for (int i = 0; i < randArray.length; i++) { randArray[i] /= sum; randArray[i] *= m; } return randArray; } 

在testing运行中, getRandDistArray(5, 1.0)返回以下内容:

 [0.38106150346121903, 0.18099632814238079, 0.17275044310377025, 0.01732932296660358, 0.24786240232602647] 

这个问题相当于用Dirichlet分布产生随机数的问题。 为了生成总和为正数M的N个正数,其中每个可能的组合是相等可能的:

  • 生成N个指数分布的随机数。 产生这样一个数字的一​​种方法可以写成:

     number = -ln(1.0 - RNDU()) 

    其中ln(x)ln(x)的自然对数, RNDU()是返回随机数0或更大且小于1的方法(例如,JavaScript的Math.random() )。 请注意,生成具有均匀分布的数字并不理想,因为会产生随机数组合的偏倚分布。

  • 把这样产生的数字除以他们的总和。
  • 每个数字乘以M.

结果是Dirichlet分布中的N个数,其总和近似等于M(由于舍入误差,我说“近似”)。

这个问题也等同于从N维单纯形产生随机数的问题。

你的约束有点苗条。 很多程序都可以运行。

例如,数字是否正常分配? 制服?
我假定所有的数字都必须是正数,均匀分布在均值M / N周围。

尝试这个。

  1. 平均值= M / N。
  2. 生成0到2 *之间的N-1值。 这可以是0和1之间的标准数字, u ,随机值是(2 * u-1)*意味着在适当的范围内创build一个值。
  3. 计算N-1值的总和。
  4. 余下的值是N-sum。
  5. 如果剩余的值不符合约束条件(0到2 * mean),则重复该过程。