How do I generate 10 random decimal numbers between -1 and 1, with these 10 numbers sum up to 1? (in Python code) Technically it is not random with the criteria sets, but how to make it as random as possible.
-
The answer would be infinite. I would start by specifying a number of decimal places. – MVB76 Sep 01 '20 at 02:37
-
Generate 10 random numbers, in whatever range you want. Divide all of them by their total, the results will necessarily total to 1. – jasonharper Sep 01 '20 at 02:42
-
That will get the total to 1, but the range of the numbers will no longer be between -1 and 1... – Jiří Baum Sep 01 '20 at 02:46
-
To add some richness, this question is very very close to random sampling in a 9-simplex https://cs.stackexchange.com/questions/3227/uniform-sampling-from-a-simplex. I'm not immediately sure how to change the interval from (0,1) to (-1,1), but the linked algorithm could be a good place to start. – abatea Sep 01 '20 at 04:26
-
Does this answer your question? [Generating a list of random numbers, summing to 1](https://stackoverflow.com/questions/18659858/generating-a-list-of-random-numbers-summing-to-1) – Adhun Thalekkara Sep 01 '20 at 08:47
-
I got stuck on the (-1,1)range. Summing to 1 is relatively easier to achieve. I think this link only shows how to add up to 1? – h s Sep 01 '20 at 16:16
3 Answers
Create a for loop that adds each generated numbers. At the end of the for loop use an if statement to check if the total is equal to 1, if not equal to 1 re-generate 10 random numbers and repeat the process. However, I don't recommend you to do this if you are looking for a way to do this process instantly because it might take a while since the generated numbers are random.

- 56
- 2
- 11
-
This will require an approximately infinite number of loops, since total being equal to 1 has probability zero (in mathematical real numbers) and approximately zero (in IEEE floating-point numbers)? – Jiří Baum Sep 01 '20 at 03:03
-
@sabik Yes that's a good point and i agree with your statement. That's why I have said that it might take a while to get the result cause it has a very small probability percentage. But this would be the simplest approach which would not be a very good way. – Volvo Sep 01 '20 at 04:03
-
@sabik you are absolutely right, I have tried this brute force method and it ran forever. – h s Sep 01 '20 at 16:17
Hmm, two approaches:
Simple but somewhat brute-force: generate 9 variables in the range -1 to 1 (using either
random
orsecrets
, as appropriate); calculate the 10th one so the total is 1; repeat the whole process until the 10th variable is in the range -1 to 1.This will be relatively fast, because the total of the first 9 variables must in any case be in the range -9 to 9, and you need it to be in the range 0 to 2 in order to get a valid variable 10. A handful to a dozen iterations should do it.
Work out the shape of the 9-dimensional object in 10-dimensional space that you're sampling from, on paper. Once you know its shape, you can sample from the 9-dimensional object and apply the relevant rotation in the 10 dimensions.

- 6,697
- 2
- 17
- 17
Here's a solution based on random sampling an n-simplex (https://cs.stackexchange.com/questions/3227/uniform-sampling-from-a-simplex):
def sample(n=10):
L = sorted([0, *(random.uniform(0,1) for _ in range(n-1)), 1])
return [2*(1/n-(b-a)) + 1/n for a,b in zip(L[:-1], L[1:])]
It sometimes produces samples outside your (-1,1) bounds. Luckily, the rate of samples needing to be rejected is something like 10 per 10k samples for n=10.
Also keep in mind that this is distributed on a simplex (triangle, tetrahedron, etc) so it won't have a uniform distribution in the individual variables.

- 81
- 1
- 8