Python 如何生成和等于特定数字的15个随机数

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

我有一个随机颜色选择器的代码,但不是随机数。我需要它在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.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]