Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting N random numbers whose sum is M

I want to get N random numbers whose sum is a value.

For example, let's suppose I want 5 random numbers that sum to 1.

Then, a valid possibility is:

0.2 0.2 0.2 0.2 0.2

Another possibility is:

0.8 0.1 0.03 0.03 0.04

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

like image 207
marionmaiden Avatar asked Apr 14 '10 18:04

marionmaiden


4 Answers

Short Answer:

Just generate N random numbers, compute their sum, divide each one by the sum and multiply by M.

Longer Answer:

The above solution does not yield a uniform distribution which might be an issue depending on what these random numbers are used for. Another method 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.

This yields a uniform distribution as is explained here

like image 137
Guillaume Avatar answered Nov 09 '22 02:11

Guillaume


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.

like image 37
Matti Virkkunen Avatar answered Nov 09 '22 02:11

Matti Virkkunen


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."

like image 27
Accipitridae Avatar answered Nov 09 '22 03:11

Accipitridae


Unfortunately, a number of the answers here are incorrect if you'd like uniformly random numbers. The easiest (and fastest in many languages) solution that guarantees uniformly random numbers is just

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

where n is the number of random numbers you want to generate and m is the sum of the resulting array. This approach produces positive values and is particularly useful for generating valid probabilities that sum to 1 (let m = 1).

like image 6
cgnorthcutt Avatar answered Nov 09 '22 02:11

cgnorthcutt