[英]Generate random value from a range of number for a fixed limit in python
代码:
import random
import numpy as np
X=10
Y=5
while True:
random_value=np.random.choice((range(1,X)),Y)
if sum(random_value)==X:
break
else:
continue
问题
此代码适用于 X 和 Y 的小值,但不适用于 X=56 和 Y=52 等大值。我的目标是从列表中的 X 生成随机值,其大小为 Y 以及随机值应该是 b X
我应该如何优化代码以获得大值的 output
这是一些工作代码。 在像X = 56
和Y = 52
这样的情况下,大多数数字都是 1,因此这段代码计算出需要多少个 1,生成其他数字,然后从这些随机数中减去或添加这些随机数,直到它们总和为所需的金额。
import numpy as np
import random
def get_vals_from_X_Y(X, Y):
# If X = 56 and Y = 55, can have a single 2 in generated values and then 54 ones.
# If X = 56 and Y = 54, can have 2 twos and 52 ones.
# Pattern is that you need (Y - (X - Y)) ones, which simplifies to (2Y - X).
# This pattern ONLY APPLIES if Y >= X / 2. If Y < X / 2, then every Y value needs to be >= 2.
if Y >= X / 2:
num_1s_needed = 2*Y - X
else:
num_1s_needed = 0
# vals will eventually contain Y values summing to X.
vals = []
vals = [1]*num_1s_needed
# What the random numbers need to sum to. It's X minus all the ones.
sum_needed = X - num_1s_needed
if sum_needed == 0:
return vals
elif sum_needed == 1:
idx = random.randrange(num_1s_needed-1)
vals.insert(idx, 1)
return vals
else:
# places_left determines how many random numbers to generate.
places_left = Y - num_1s_needed
random_vals = [random.randrange(1, sum_needed) for i in range(places_left)]
# If sum of random_vals is too small, add randomly to a value as needed.
while sum(random_vals) < sum_needed:
idx_to_add_to = random.randrange(len(random_vals))
if random_vals[idx_to_add_to] < X:
random_vals[idx_to_add_to] += 1
# Sort from big to small and find the first instance of 1.
# Add all 1s to vals and remove from random_vals.
# Adjust sum_needed to always be X - len(vals).
random_vals.sort(reverse=True)
try:
idx_1 = random_vals.index(1)
orig_length = len(random_vals)
random_vals = random_vals[:idx_1]
vals += [1]*(orig_length - len(random_vals))
sum_needed -= (orig_length - len(random_vals))
# If there is no 1 in random_vals, function will go to the except block.
except:
pass
# Subtract as needed from a random value that is greater than 1.
while sum(random_vals) > sum_needed:
idx_to_subtract_from = random.randrange(len(random_vals))
if random_vals[idx_to_subtract_from] > 1:
random_vals[idx_to_subtract_from] -= 1
# Generate a random index and insert each random_val into vals at that index.
for i in range(len(random_vals)):
idx = 0
if len(vals) > 1:
idx = random.randrange(len(vals))
vals.insert(idx, random_vals[i])
return vals
# Change X and Y to your liking.
vals = get_vals_from_X_Y(X, Y)
让我知道是否需要澄清。
您可以从合适的多项式分布中采样,但给定范围[1..limit-1]
通常不会在结果中耗尽,即使可能。
import numpy as np
rng = np.random.default_rng()
N = 52
limit = 56
a = rng.multinomial(limit - N, np.full(N, 1.0/N)) + 1
print(a)
print(f'sum:{a.sum()}, length:{a.shape[0]}')
Output(随机)
[1 2 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1]
sum:56, length:52
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.