views:

524

answers:

7

Hello

I want to get N random numbers that the sum of them is a value.

For example, let's suppose I want 5 random numbers that their sum is 1

Then, a valid possibility is:

0.2 0.2 0.2 0.2 0.2

Other possibility is:

0.8 0.1 0.03 0.03 0.04

And so on. I need this for the creation of the matrix of belongings of the Fuzzy C-means.

+18  A: 

Just generate N random numbers, compute their sum, divide each one by the sum

Guillaume
Then multiply by M (unless M is 1 like in the example).
ILMTitan
I had just found this same solution! I should have researched more before I asked it. Shame on me...
marionmaiden
+2  A: 

Generate N-1 random numbers between 0 and 1, add the numbers 0 and 1 themselves to the list, sort them, and take the differences of adjacent numbers.

Matti Virkkunen
All right, this was overly complicated. Maybe useful if someone wants to limit it to integers though (obviously using a range larger than 0 to 1)
Matti Virkkunen
It is not immediately obvious to me that this will result in a normal distribution for N > 3
ILMTitan
I make no guarantees about math I don't fully understand.
Matti Virkkunen
It looks like this is the only solution so far that results in a uniform distribution (unless I made a mistake verifying this, which is always possible).
Accipitridae
A: 

You're a little slim on constraints. Lots and lots of procedures will work.

For example, are numbers normally distributed? Uniform?
I'l assume that all the numbers must be positive and uniformly distributed around the mean, M/N.

Try this.

  1. mean= M/N.
  2. Generate N-1 values between 0 and 2*mean. This can be a standard number between 0 and 1, u, and the random value is (2*u-1)*mean to create a value in an appropriate range.
  3. Compute the sum of the N-1 values.
  4. The remaining value is N-sum.
  5. If the remaining value does not fit the constraints (0 to 2*mean) repeat the procedure.
S.Lott
A: 

Find a random number between 0 and the total you want. Subtract the number from the total. Repeat n-1 times. The final total is the final number.

List<Double> result= new ArrayList<Double>();
double total = 1.0;
for (int i = 0;++i < 5;) {
    double db = Math.random() * total;
    result.add( db );
    total -= db;
}
result.add( total );
Matthew Flynn
Again, this won't work most of the time because the last number will most likely be negative.
Blindy
Math.random() returns a number between 0 and 1. "total" is the difference between value n (initially 0.0) and the upper limit (1.0) The product of the two numbers can never be greater than "total". The value of "total" is updated each iteration:n1 = random * 1, n2 = random * (1 - n1), n3 = random * ((1 - n1) - n2), n4 = random * (((1- n1) -n2) -n3), n5 = (((1 - n1) - n2) - n3) - n4. There's no way n5 can be less than 0. Try it.
Matthew Flynn
A: 
  1. Generate N-1 random numbers.
  2. Compute the sum of said numbers.
  3. Add the difference between the computed sum and the desired sum to the set.

You now have N random numbers, and their sum is the desired sum.

Yuval
Except if you get the last number to be negative.
Blindy
Nothing in the question prohibits negative values...
Yuval
+2  A: 

In 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;
}
Vortico
> Then multiply by M (unless M is 1 like in the example). – ILMTitan Apr 14 at 18:49
Tobias Kienzler
Ah. I missed that. Thanks!
Vortico
+1  A: 

I think it is worth noting that the currently accepted answer does not give a uniform distribution:

"Just generate N random numbers, compute their sum, divide each one by the sum"

To see this let's look at the case N=2 and M=1. This is a trivial case, since we can generate a list [x,1-x], by choosing x uniformly in the range (0,1). The proposed solution generates a pair [x/(x+y), y/(x+y)] where x and y are uniform in (0,1). To analyze this we choose some z such that 0 < z < 0.5 and compute the probability that the first element is smaller than z. This probaility should be z if the distribution were uniform. However, we get

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

I did some quick calculations and it appears that the only solution so far that appers to result in a uniform distribution was proposed by Matti Virkkunen:

"Generate N-1 random numbers between 0 and 1, add the numbers 0 and 1 themselves to the list, sort them, and take the differences of adjacent numbers."

Accipitridae