根据代码,我想随机化指定特定范围的整数,但在最后三个数组中我总共需要有
100
。最后三个数组的总和不能超过100
。我不知道如何解决这个问题。
self.position = np.array([rd.randint(0,2), rd.randint(0,2), rd.randint(0,100), rd.randint(0,50), rd.randint(0,1)])
虽然解决方案Rmano建议是有效的,但它缺乏完全的随机性,因为一旦你绘制第一个随机整数,其他整数就会是伪随机的,或者由于依赖而根本不是随机的。
在我看来,更随机的解决方案是:
import numpy as np
def generate_fix_sum_random_vec(limit, num_elem, tries=10):
v = np.random.randint(0, limit, num_elem)
s = sum(v)
if (np.sum(np.round(v/s*limit)) == limit):
return np.round(v / s * limit)
elif (np.sum(np.floor(v/s*limit)) == limit):
return np.floor(v / s * limit)
elif (np.sum(np.ceil(v/s*limit)) == limit):
return np.ceil(v / s * limit)
else:
return generate_fix_sum_random_vec(limit, num_elem, tries-1)
for i in range(25):
test_vec = generate_fix_sum_random_vec(100, 3)
test_vec = test_vec.astype(int)
print("vec: ", test_vec, "sum of vector: ", np.sum(test_vec))
这个解决方案更加鲁棒,并且可以对向量之和的任何限制有效,并且通过改变
num_elem
,它可以轻松地适用于任何长度的向量。此外,它不假设任何事情,只是尝试直到找到匹配项。
循环的输出:
vec: [53 32 15] sum of vector: 100
vec: [40 38 22] sum of vector: 100
vec: [56 38 6] sum of vector: 100
vec: [ 5 17 78] sum of vector: 100
vec: [12 29 59] sum of vector: 100
vec: [ 1 34 65] sum of vector: 100
vec: [ 3 56 41] sum of vector: 100
vec: [35 65 0] sum of vector: 100
vec: [54 9 37] sum of vector: 100
vec: [45 8 47] sum of vector: 100
vec: [30 56 14] sum of vector: 100
vec: [34 63 3] sum of vector: 100
vec: [17 40 43] sum of vector: 100
vec: [56 36 8] sum of vector: 100
vec: [52 45 3] sum of vector: 100
vec: [35 34 31] sum of vector: 100
vec: [25 41 34] sum of vector: 100
vec: [ 1 78 21] sum of vector: 100
vec: [ 1 49 50] sum of vector: 100
vec: [51 31 18] sum of vector: 100
vec: [50 10 40] sum of vector: 100
vec: [36 63 1] sum of vector: 100
vec: [30 30 40] sum of vector: 100
vec: [27 30 43] sum of vector: 100
vec: [21 27 52] sum of vector: 100
需要检查结果向量和是否确实达到所需值,因为这不能保证
我不确定你会得到多少随机性,但是:
def three_to_100_b():
a3 = random.randint(0,1)
a2 = random.randint(0,50)
a1 = 100-a3-a2
return a1, a2, a3
会给你三个 pseudo - 随机数,第一个在 0-100 范围内,第二个在 0-50 范围内,最后一个是 0 或 1,总和为 100。
但请注意,
a1
和a2
之间的随机性非常小——根据定义,它们位于一条直线+0或-1上......
让三个数字之和为 100 的一种方法是生成三个随机数,然后缩放它们,使它们的总和为 100。这过于冗长,但其想法是:
#! /usr/bin/env python3
import random
def three_to_100():
r1 = random.randint(0,100)
r2 = random.randint(0,100)
r3 = random.randint(0,100)
a1 = r1*100/(r1+r2+r3)
a2 = r2*100/(r1+r2+r3)
a3 = 100 - a1 - a2
return a1, a2,a3
#main
print("x\t y\t z")
for i in range(1000):
# print(three_to_100())
a=three_to_100()
print("{}\t {}\t {}".format(*a))
我绘制了前 1000 个数字的 (x,y) 对(第三个数字由点的颜色表示),我有:
您可以生成一个 0 到 100 之间的数字,然后生成另一个 0 到(100 - 第一个数字)之间的数字,依此类推。最后一个不会是随机的:
#! /usr/bin/env python3
import random
def three_to_100():
r1 = random.randint(0,100)
r2 = random.randint(0,100-r1)
r3 = 100 - r1 - r2
return r1, r2,r3
#main
for i in range(10):
print(three_to_100())
输出将是:
[romano:~/tmp] % ./randsum.py
(26, 7, 67)
(85, 13, 2)
(43, 41, 16)
(75, 22, 3)
(66, 19, 15)
(30, 16, 54)
(43, 30, 27)
(36, 2, 62)
(31, 2, 67)
(91, 0, 9)
这是前两个数字的图 - 它们看起来相当随机,但也许它们在 x-y 轴上看起来有点拥挤。
下面是 numpy 的答案。它无需重试逻辑即可工作
def randint_sum_total(num_elem, min, max, total_limit):
"""It will create random numbers between min and max range but the sum will match the expected_total
Args:
size (int): number of items
min (int): minimum value
max (int): max value
limit (int): sum of all values should match this
Returns:
array: list contains random numbers
"""
random_numbers = (np.random.uniform(min, max, num_elem)).astype(int)
scaled_numbers = random_numbers / random_numbers.sum() * total_limit
# Round the scaled numbers to integers
rounded_numbers = np.round(scaled_numbers).astype(int)
rounded_numbers[rounded_numbers<min] = min # if the scaled num less than min_range , add min_range
rounded_numbers[rounded_numbers>max] = max # if the scaled num greater than max_range , add max_range
remaining = total_limit - rounded_numbers.sum()
indices = np.where((rounded_numbers + remaining > min) & (rounded_numbers + remaining < max))
if len(indices[0]) > 0: # Check if there are values in the range (min_range , max_range)
# Add remaining to the first value meeting the condition
rounded_numbers[indices[0][0]] += remaining
return rounded_numbers