Python 如何生成和等于特定数字的15个随机数
我有一个随机颜色选择器的代码,但不是随机数。我需要它在5到20之间选择一个15次的随机数,但问题是所有15个数的总和必须等于227 我有一个随机颜色生成器的代码,但我不知道如何生成数字以及如何得到227个Python 如何生成和等于特定数字的15个随机数,python,random,Python,Random,我有一个随机颜色选择器的代码,但不是随机数。我需要它在5到20之间选择一个15次的随机数,但问题是所有15个数的总和必须等于227 我有一个随机颜色生成器的代码,但我不知道如何生成数字以及如何得到227个 import turtle import random turtle.bgcolor("black") t = turtle.Pen() t.width(4) colours = ["yellow", "orange", "red"] for i in range(60): t.pe
import turtle
import random
turtle.bgcolor("black")
t = turtle.Pen()
t.width(4)
colours = ["yellow", "orange", "red"]
for i in range(60):
t.pencolor(colours[random.randint(0,2)])
t.forward(100)
t.back(100)
t.left(6)
如果你不在乎这些数字是否是严格随机的,你可以生成14个介于5和20之间的随机数字,检查这些数字的总和是否足够接近你想要的总数227(这样在5和20之间再加一个数字就会达到227),然后加上相应的“缺失”数字 以下函数正是这样做的:
def rng_list():
while True:
rng_list = [random.randint(5, 20) for _ in range(14)]
if 207 <= sum(rng_list) <= 222:
break
rng_list.append(227 - sum(rng_list))
return rng_list
def rng_list():
尽管如此:
rng_list=[random.randint(5,20)表示范围(14)]
如果207让我们分析问题:
我们将生成14个数字,并手动将15个数字相加,以获得正确的总和
但我会改变@jfaccioni一次生成所有数字的方法,并更早地重新启动循环:例如,如果我们生成5次5次,我们已经知道我们无法得到正确的和!(5*5+20*(15-5)<227)
(为了更好的可读性,在输出中添加了空行。)对于这类问题,正确的答案是——根据定义,总和等于所需的数字。在Python中,它几乎是一行程序
q = np.random.multinomial(227, [1/15.]*15)
np.sum(q)
将打印
227
然后你可以应用拒绝/接受技巧:
if np.any(q < 5):
# reject and start again
if np.any(q > 20):
# reject and start again
# accept, do something with the sampled array
如果np.有(q<5):
#拒绝并重新开始
如果np.有(q>20):
#拒绝并重新开始
#接受,对采样的数组执行某些操作
或者以函数形式
import numpy as np
def sample(nof_samples, min, max, sum):
p = np.full(nof_samples, 1.0/np.float64(nof_samples)) # probabilities
while True:
q = np.random.multinomial(sum, p)
if not np.any(q > max):
if not np.any(q < min):
return q
t = sample(15, 5, 20, 227)
print(t)
t = sample(15, 5, 20, 227)
print(t)
t = sample(15, 5, 20, 227)
print(t)
将numpy导入为np
def样本(nof_样本、最小值、最大值、总和):
p=np.full(nof_样本,1.0/np.float64(nof_样本))#概率
尽管如此:
q=np.随机多项式(和,p)
如果不是np.any(q>最大值):
如果不是np.任何(q
您需要15个加起来等于227的数字。227/15 = 15.133. 从[15,15,…,15,16,16]开始,加起来是227(15 x 15=225)
现在对a)保持总数不变的数字对进行随机更改,b)不要将数字推到5..20限制之外
一种方法是随机选择2个数字,检查这两个数字离限制有多远,并使用该信息选择随机大小更改。将尺寸更改添加到一对中,然后从另一对中减去。然后选择另一对并重复
ETA:不要随机挑选两个成员。使用类似Fisher-Yates shuffle的方法,其中一对成员按顺序在列表中运行,从而确保列表中的每个成员在每次通过列表时至少被处理一次。套用Severin Pappadeux的答案,您可以通过从min
和max
中减去5来消除下限拒绝的需要,对于这个特定问题,将它们设为0和15。这将目标sum
减少nof_samples*min
。一旦一个集合通过了缩减上限检查,就不需要检查下限冲突,因为它现在是0,并且所有结果都是正的。我们只需要通过将min
添加回所有值来转换这些结果,以将它们恢复到原始范围
import numpy as np
import sys
def sample(nof_samples, min, max, sum):
p = np.full(nof_samples, 1.0/np.float64(nof_samples)) # probabilities
sum -= nof_samples * min
max -= min
if sum < 0 or sum > nof_samples * max: # check that args have a feasible solutioon
print('Inconceivable!')
sys.exit()
while True:
q = np.random.multinomial(sum, p)
if not np.any(q > max):
return q + min
for _ in range(3):
t = sample(15, 5, 20, 227)
print(t)
print(min(t), max(t), sum(t)) # confirm that all constraints have been met
生产,例如
[ 0 1 -1 4 -5]
这有点重复,但这个问题的不寻常之处在于,5到20之间的15个数字的期望值是187.5,远低于227。因此,这个约束似乎非常重要。不过,更重要的是,总的来说,这是一个很好的问题和答案。@aschultz我同意这些限制使这成为一个不同的问题,并投票决定重新开始。
import numpy as np
import sys
def sample(nof_samples, min, max, sum):
p = np.full(nof_samples, 1.0/np.float64(nof_samples)) # probabilities
sum -= nof_samples * min
max -= min
if sum < 0 or sum > nof_samples * max: # check that args have a feasible solutioon
print('Inconceivable!')
sys.exit()
while True:
q = np.random.multinomial(sum, p)
if not np.any(q > max):
return q + min
for _ in range(3):
t = sample(15, 5, 20, 227)
print(t)
print(min(t), max(t), sum(t)) # confirm that all constraints have been met
print(sample(5, -10, 20, -1))
[ 0 1 -1 4 -5]