获得N个随机数,其总和为M.

时间:2010-04-14 18:37:39

标签: random language-agnostic sum

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

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

然后,有效的可能性是:

0.2 0.2 0.2 0.2 0.2

另一种可能性是:

0.8 0.1 0.03 0.03 0.04

等等。我需要这个来创建模糊C均值的所有物矩阵。

9 个答案:

答案 0 :(得分:54)

简答:

  

只需生成N个随机数,计算它们的总和,将每个数除以   总和并乘以M.

更长的答案:

上述解决方案会产生均匀分布,这可能是一个问题,具体取决于这些随机数的用途。 Matti Virkkunen提出的另一种方法:

  

生成介于0和1之间的N-1个随机数,添加数字0和1   他们自己到列表,排序他们,并采取不同的   相邻的数字。

我不确定这是否会产生均匀分布

答案 1 :(得分:41)

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

答案 2 :(得分:26)

我认为值得注意的是the currently accepted answer没有给出统一的分布:

  

“只需​​生成N个随机数,   计算它们的总和,将每一个除以   总和“

为了看到这一点,我们来看看N = 2和M = 1的情况。这是一个简单的情况,因为我们可以通过在范围(0,1)中统一选择x来生成列表[x,1-x]。 所提出的解决方案生成一对[x /(x + y),y /(x + y)],其中x和y在(0,1)中是均匀的。为了分析这个,我们选择一些z,使得0 <0。 z&lt; 0.5并计算出概率 第一个元素小于z。如果分布是均匀的,那么这个概率应该是z。但是,我们得到

  

Prob(x /(x + y)&lt; z)= Prob(x

我做了一些快速计算,看来到目前为止唯一可以导致统一分布的解决方案是proposed by Matti Virkkunen

  

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

答案 3 :(得分:4)

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

答案 4 :(得分:2)

  

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

Expanding on Guillaume's accepted answer,这是一个完全正确的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;
}

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

[0.38106150346121903, 0.18099632814238079, 0.17275044310377025, 0.01732932296660358, 0.24786240232602647]

答案 5 :(得分:2)

This problem相当于使用Dirichlet distribution生成随机数的问题。要生成总和为正数M的N个正数,其中每个可能的组合同样可能:

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

    number = -ln(1.0 - RNDU())
    

    其中ln(x)x的自然对数,而RNDU()是一个返回0或更大且小于1的随机数的方法(例如,JavaScript&#39; s {{ 1}})。请注意,生成具有均匀分布的数字并不理想,因为会产生随机数组合的偏差分布。

  • 将以这种方式生成的数字除以其总和。
  • 将每个数字乘以M.

结果是Dirichlet分布中的N个数,其和大约等于M(我说&#34;大约&#34;因为舍入误差)。

这个问题也等同于generating random numbers uniformly from an N-dimensional simplex

的问题

答案 6 :(得分:1)

  1. 生成N-1个随机数。
  2. 计算所述数字的总和。
  3. 将计算的总和与所需总和之间的差值添加到集合中。
  4. 您现在有N个随机数,它们的总和是所需的总和。

答案 7 :(得分:1)

不幸的是,如果您想要统一的随机数,那么这里的许多答案都是错误的。保证统一随机数的最简单(也是许多语言中最快)的解决方案就是

# This is Python, but most languages support the Dirichlet.
import numpy as np
np.random.dirichlet(np.ones(n))*m

其中n是要生成的随机数,而m是结果数组的总和。这种方法会产生正值,对于生成合计为1(令m = 1)的有效概率特别有用。

答案 8 :(得分:0)

你在约束方面有点渺茫。很多很多程序都可以使用。

例如,数字是否正常分布?统一?
我假设所有数字必须是正数且均匀分布在均值M / N附近。

试试这个。

  1. mean = M / N。
  2. 生成介于0和2 *之间的N-1值。这可以是介于0和1之间的标准数字, u ,随机值为(2 * u-1)*表示在适当的范围内创建值。
  3. 计算N-1值的总和。
  4. 剩余价值是N-sum。
  5. 如果剩余值不符合约束(0到2 *均值),请重复此过程。