3
$\begingroup$

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?

$\endgroup$
9

4 Answers 4

9
$\begingroup$

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}
Out[2]=0.252736
$\endgroup$
5
  • $\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, 2014 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, 2014 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, 2014 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$ Dec 27, 2014 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, 2016 at 15:34
9
$\begingroup$

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.

$\endgroup$
0
7
$\begingroup$
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?

$\endgroup$
5
  • $\begingroup$ Aha! I should have noticed that Normalize[,Total] can be used here as a trick in the other answer you gave me. $\endgroup$ Dec 26, 2014 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, 2014 at 23:51
  • $\begingroup$ @Sungmin The OP here haven't used the word "uniform" ... $\endgroup$ Dec 26, 2014 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, 2014 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$ Dec 27, 2014 at 0:09
1
$\begingroup$

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}
$\endgroup$
3
  • 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, 2014 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, 2014 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, 2014 at 9:15

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