【问题标题】:Python: Generate n random integer numbers between two values summing up to a given numberPython:在两个值之间生成n个随机整数,总和为给定数字
【发布时间】:2018-12-26 21:14:06
【问题描述】:

我非常想在两个值(minmax)之间生成n随机整数,其总和等于给定数字m

注意:我在 StackOverflow 中发现了类似的问题;但是,它们并没有完全解决这个问题(使用Dirichlet 函数,因此数字介于0 和1 之间)。

示例:我需要 8 个介于 0 和 24 之间的随机数(整数),其中 8 个生成的数字之和必须等于 24。

感谢任何帮助。谢谢。

【问题讨论】:

  • 到目前为止您尝试过什么?如果我们有事情要做,也许我们可以帮忙......
  • 这不是“随机的”。你的意思是找到从 0 到 24 的所有 8 个整数的集合,它们相加为 24,然后随机选择其中一个? (如果是这样,第一部分有点意思,第二部分很琐碎,所以基本上归结为第一部分。)
  • 阅读 this 和 Wiki 链接以获取算法
  • 你可以使用像stackoverflow.com/questions/53279807/…这样的多项式

标签: python random integer


【解决方案1】:

好吧,您可以使用整数分布,它自然地总和为某个固定数字 - Multinomial 一。

只要来回移动,它应该会自动工作

代码

import numpy as np

def multiSum(n, p, maxv):
    while True:
        v  = np.random.multinomial(n, p, size=1)
        q  = v[0]
        a,  = np.where(q > maxv) # are there any values above max
        if len(a) == 0: # accept only samples below or equal to maxv
            return q

N = 8
S = 24
p = np.full((N), 1.0/np.float64(N))

mean  = S / N
start = 0
stop  = 24
n = N*mean - N*start

h = np.zeros((stop-start), dtype=np.int64)
print(h)
for k in range(0, 10000):
    ns = multiSum(n, p, stop-start) + start # result in [0...24]
    #print(np.sum(ns))
    for v in ns:
        h[v-start] += 1

print(h)

【讨论】:

    【解决方案2】:

    这是partition number theory 的情况。这是解决方案。

    def partition(n,k,l, m):
        if k < 1:
            raise StopIteration
        if k == 1:
            if n <= m and n>=l :
                yield (n,)
            raise StopIteration
        for i in range(l,m+1):
            for result in partition(n-i,k-1,i,m):                
                yield result+(i,)
    
    n = 24 # sum value
    k = 8 # partition size
    l = 0 # range min value
    m = 24 # range high value 
    
    result = list(partition(n,k,l,m ))
    

    这将给出满足条件的所有组合。 ps 这很慢,因为它给出了该分区大小的所有情况。

    【讨论】:

    • 分区的问题是随机性很小。
    • @SeverinPappadeux 是的,没错。但是随机性不是分区的子集,其中生成的第一个尝试找出条件是否发生?一个随机的情况可能是。
    • 如果你想让它看起来像随机的,你必须在生成器顶部添加类似 Fisher-Yates shuffle 的东西
    【解决方案3】:

    这是一种基于this 答案的可能解决方案。似乎dirichlet 方法仅在 0 和 1 之间起作用。应该对原始答案给予充分的评价。一旦您评论它符合您的目的,我将很乐意将其删除。

    不要忘记为原始答案投票。

    target = 24
    
    x = np.random.randint(0, target, size=(8,))
    while sum(x) != target: 
        x = np.random.randint(0, target, size=(8,))
    
    print(x)
    # [3 7 0 6 7 0 0 1]
    

    【讨论】:

    • 这正是我想要的。谢谢。
    猜你喜欢
    • 2018-07-18
    • 2014-09-10
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    相关资源
    最近更新 更多