In here, it works with "Integer".

What if I want 5 positive real numbers that sum to 1?

RandomChoice[IntegerPartitions[100, {5}]]/100.

That will work. But only up to two decimals places.

RandomChoice[IntegerPartitions[10^n, {5}]]/10.^n

it works fine up to n decimals. But it is really SLOW.

Is there a better way, to generate n random numbers between 0 and 1, sum to 1?


In my comments to other posts, I was being pedantic, since the randomness should be correctly defined before any algorithm is introduced.

Under this ambiguity, in my opinion, one of the natural ways to get random numbers is DirichletDistribution(http://en.wikipedia.org/wiki/Dirichlet_distribution). However, it has a degree of freedom to change the shape parameters (so still infinitely many distributions that fulfill OP's needs). In Mathematica, there is a built-in function to get it.

a = RandomVariate[ DirichletDistribution[5 {1, 1, 1, 1, 1}]]
last =  1 - Total@a

Out[1]={0.178846, 0.0756468, 0.299595, 0.193177}
  • $\begingroup$ +1. Using DirichletDistribution[{1, 1, 1, 1, 1}] gives the same distribution as the method described by Vynce, i.e. uniformly distributed on the simplex $\sum x_i=1, x_i\ge 0$. $\endgroup$ – user484 Dec 27 '14 at 12:17
  • $\begingroup$ @Rahul I also tried to prove your assersion but found it not straightforward . Thanks for the verification. $\endgroup$ – Sungmin Dec 27 '14 at 12:55
  • $\begingroup$ One can simply verify that PDF[DirichletDistribution[{1, 1, 1, 1, 1}], {a, b, c, d}] is constant inside the simplex. $\endgroup$ – user484 Dec 27 '14 at 13:47
  • 2
    $\begingroup$ An advantage of using the Dirichlet will be access to all manner of analytical results based on this being a known entity and not just a hack. $\endgroup$ – conjectures Dec 27 '14 at 20:38
  • $\begingroup$ What if I want to make them added upto an arbitrary values? for example, 4 uniform variable in [0,1] added up to a real value in [0, 4], say 2.5. $\endgroup$ – LifeWorks Feb 4 '16 at 15:34

The most straightforward algorithm, I would think, is to pick 4 random numbers inthe range (0,1); sort them, and then find the difference between each adjacent pair (using 1 and 0 as the end points).

e.g., choose four numbers:

[0.23, 0.0456, 0.7, 0.98]

sort them:

0.0456, 0.23, 0.7, 0.98

0.0456 - 0 = 0.0456 0.23 - 0.0456 = 0.1744 0.7 - 0.23 = 0.47 0.98 - 0.7 = 0.28 1 - 0.98 = 0.02

answers: [0.0456, 0.1744, 0.47, 0.28, 0.02]

you could then restrict this to whatever level of precision you want by rounding or truncating in the first step.

A completely different approach, which will result in a different distribution, is to initialize your running total as zero, and then pick a random number from 0 to (target - running total); add that to your running total. repeat until you have 1 fewer numbers than you need, and then your fifth number is 1 - your total so far.

In both cases, I'll leave the syntax up to you.

rand5Sum1[] := Normalize[RandomReal[{0, 1}, 5], Total]

The distribution of each number results in:

Histogram[Table[rand5Sum1[], {100000}] // Flatten]

Mathematica graphics

Don't know if it has a name ... Anyone?

  • $\begingroup$ Aha! I should have noticed that Normalize[,Total] can be used here as a trick in the other answer you gave me. $\endgroup$ – Chen Stats Yu Dec 26 '14 at 22:51
  • 1
    $\begingroup$ In the one of the answer of the post I linked above, there is an argument that this approach does not give a certain sense of "uniformly distributed-ness". I still feel the algorithm should be taken in a more rigorous way even though OP does not seem to have a clear definition of randomness. I just want to point out the subtlety of the given problem for the record. $\endgroup$ – Sungmin Dec 26 '14 at 23:51
  • $\begingroup$ @Sungmin The OP here haven't used the word "uniform" ... $\endgroup$ – Dr. belisarius Dec 26 '14 at 23:57
  • $\begingroup$ That is correct. In that sense, the problem is ill-defined. As I said earlier, I just wanted to warn the future readers that there might be a subtlety in this problem that was discussed in various other posts in stackoverflow. Did not intend to offend your answer. $\endgroup$ – Sungmin Dec 27 '14 at 0:03
  • $\begingroup$ @Sungmin No offense. I posted my answer after pondering what kind of distribution the OP could want. Not sure tough. $\endgroup$ – Dr. belisarius Dec 27 '14 at 0:09

Here's one way: pick four random reals (with sum less than one) and then pick the fifth so that the sum is equal to 1. I'm not sure how important it is, but I chose the first number to have mean 0.2, which is what you would expect the mean of the five numbers to be.

f[r_] := Flatten@{r, RandomReal[{0, 1 - Total[r]}]};
rand4 = Nest[f, {RandomReal[{0, 0.4}]}, 3];
rand5 = Flatten@{rand4, 1 - Total@rand4}

A few runs:

{0.0696461, 0.428977, 0.179359, 0.123855, 0.198163}

{0.0810309, 0.0571466, 0.510828, 0.109318, 0.241676}

{0.275299, 0.152319, 0.123827, 0.23648, 0.212075}
  • 1
    $\begingroup$ I am not very sure your approach gives the right randomness OP asked. stackoverflow.com/questions/3959021/… might be related. In what sense, your approach gives random numbers? $\endgroup$ – Sungmin Dec 26 '14 at 22:13
  • $\begingroup$ @Sungmin -- it isn't clear that the OP has any particular expectation for the distribution of the numbers. The OP asks only for "random" numbers. $\endgroup$ – bill s Dec 27 '14 at 5:11
  • $\begingroup$ Maybe I was being too pedantic. Please check my answer where I explained a bit why I did. $\endgroup$ – Sungmin Dec 27 '14 at 9:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.