views:

79

answers:

2

I hope I can explain this well, if I don't I'll try again.

I want to generate an array of 5 random numbers that all add up to 10 but whose allocation are chosen on an interval of [0,2n/m].

I'm using numpy.

The code I have so far looks like this:

import numpy as np

n=10
m=5
#interval that numbers are generated on
randNumbers= np.random.uniform(0,np.divide(np.multiply(2.0,n),fronts),fronts)
#Here I normalize the random numbers
normNumbers = np.divide(randNumbers,np.sum(randNumbers))
#Next I multiply the normalized numbers by n
newList = np.multiply(normNumbers,n)
#Round the numbers two whole numbers
finalList = np.around(newList)

This works for the most part, however the rounding is off, it will add up to 9 or 11 as opposed to 10. Is there a way to do what I'm trying to do without worrying about rounding errors, or maybe a way to work around them? If you would like for me to be more clear I can, because I have trouble explaining what I'm trying to do with this when talking :).

+1  A: 

Just generate four of the numbers using the technique above, then subtract the sum of the four from 10 to pick the last number.

Kaelin Colclasure
I think this is right. You can't pick all five numbers "randomly" and expect them to sum to a certain value.
erickson
This won't give a "fair" distribution though
gnibbler
Thanks for your help, but I decided to go with the second answer.
Elais Jackson
+1  A: 

This generates all the possible combinations that sum to 10 and selects a random one

from itertools import product
from random import choice
n=10
m=5
finalList = choice([x for x in product(*[range(2*n/m+1)]*m) if sum(x) == 10])

There may be a more efficient way, but this will select fairly between the outcomes

Lets see how this works when n=10 and m=5

2*n/m+1 = 5, so the expression becomes

finalList = choice([x for x in product(*[range(5)]*5) if sum(x) == 10])

`*[range(5)]*5 is using argument unpacking. This is equivalent to

finalList = choice([x for x in product(range(5),range(5),range(5),range(5),range(5)) if sum(x) == 10])

product() gives the cartesian product of the parameters, which in this case has 5**5 elements, but we then filter out the ones that don't add to 10, which leaves a list of 381 values

choice() is used to select a random value from the resultant list

gnibbler
This worked, thanks.
Elais Jackson
It worked, but could you kind of explain what all is going on in your last line? Just so I'd know what I'm using? I'm really quite new to python.
Elais Jackson