So here is the deal: I want to (for example) generate 4 pseudo-random numbers, that when added together would equal 40. How could this be dome in python? I could generate a random number 1-40, then generate another number between 1 and the remainder,etc, but then the first number would have a greater chance of "grabbing" more.
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
Here's the standard solution. It's similar to Laurence Gonsalves' answer, but has two advantages over that answer.
and
Sample outputs:
Explanation: there's a one-to-one correspondence between (1) 4-tuples
(a, b, c, d)
of positive integers such thata + b + c + d == 40
, and (2) triples of integers(e, f, g)
with0 < e < f < g < 40
, and it's easy to produce the latter usingrandom.sample
. The correspondence is given by(e, f, g) = (a, a + b, a + b + c)
in one direction, and(a, b, c, d) = (e, f - e, g - f, 40 - g)
in the reverse direction.If you want nonnegative integers (i.e., allowing
0
) instead of positive ones, then there's an easy transformation: if(a, b, c, d)
are nonnegative integers summing to40
then(a+1, b+1, c+1, d+1)
are positive integers summing to44
, and vice versa. Using this idea, we have:Graphical illustration of
constrained_sum_sample_pos(4, 10)
, thanks to @FM. (Edited slightly.)There are only 37^4 = 1,874,161 arrangements of four integers in the range [1,37] (with repeats allowed). Enumerate them, saving and counting the permutations that add up to 40. (This will be a much smaller number, N).
Draw uniformly distributed random integers K in the interval [0, N-1] and return the K-th permutation. This can easily be seen to guarantee a uniform distribution over the space of possible outcomes, with each sequence position identically distributed. (Many of the answers I'm seeing will have the final choice biased lower than the first three!)
Assuming you want them to be uniformly distributed, and assuming you don't want repeats
(I assume you wanted integers since you said "1-40", but this could be easily generalized for floats.)
Here's how it works:
Generate 4 random numbers, compute their sum, divide each one by the sum and multiply by 40.
If you want Integers, then this will require a little non-randomness.