Goal: split 100
into 5
random 2 decimal place numbers.
So far, I can simulate any number of divisions.
However, these are only integers and are "balanced", in that they are the same or close in values to each other. So, the output is always the same.
Code:
def split(x, n):
if(x < n):
print(-1)
elif (x % n == 0):
for i in range(n):
print(x//n, end =" ")
else:
zp = n - (x % n)
pp = x//n
for i in range(n):
if(i>= zp):
print(pp + 1, end =" ")
else:
print(pp, end =" ")
split(100, 5)
>>> 20 20 20 20 20
Desired Output:
Example Desired Output:
[10.50, 22.98, 13.23, 40.33, 12.96]
If you generate values uniformly starting with the full range for the first one, the remaining range for the second, the remaining remaining range for the third, etc., there's a 50% chance each time of getting a value larger than half the remaining range. This leads to a systematic bias—on average, earlier values tend to be larger than later values. There's a simple algorithm to avoid this and get identical distributions for all positions:
By definition the results will add up to the maximum, because they are the interval lengths between 0 and the maximum. Big gaps or small gaps are equally likely to fall between any of the pairs, guaranteeing identical distributions (to the extent that the PRNG is actually uniform).
I've adopted the idea of scaling up by 100 and back to get two decimals. Here it is in code:
import random
def split(x, n, decimal=2):
if x < n: return -1
if decimal < 0: return -1
x *= 10**decimal
numbers = [0, x]
for _ in range(n - 1):
number = random.randint(1, x)
numbers.append(number)
numbers.sort()
return [(numbers[i] - numbers[i-1]) / 10**decimal for i in range(1, n+1)]
which produces outcomes such as
[10.82, 12.97, 17.92, 39.46, 18.83]
[25.99, 21.35, 29.12, 8.13, 15.41]
[5.51, 4.28, 69.59, 9.62, 11.0]
[21.39, 20.96, 11.25, 15.07, 31.33]
You can use python's builtin random
library to specify random numbers, and keep subtracting that number from your total to generate more random numbers.
Like @Kenny Ostrom suggested, you can multiply by 100 and then divide by 100 at the end to get the desired number of decimal places. I made it more generic by adding a kwarg decimal
, in case you need a different floating point precision
import random
def split(x, n, decimal=2):
if x < n: return -1
if decimal < 0: return -1
x *= 10**decimal
numbers = []
left = x
for i in range(n):
number = random.randint(1,left)
numbers.append(number)
left -= number
return [n / 10**decimal for n in numbers]
Some example outputs
split(100,5) # [1.8, 67.64, 0.51, 21.88, 3.67]
split(100,5) # [29.29, 16.39, 51.54, 1.91, 0.71]
split(100,5) # [95.24, 0.79, 0.82, 2.56, 0.02]
split(100,5) # [10.18, 45.09, 30.87, 0.3, 0.68]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.