生成具有固定和和约束的随机整数

Wen*_*hen 5 random

如何生成6个随机整数,它们的总和为8,每个整数均小于或等于2?

例如。1,2,1,2,2,0

到目前为止,我已经找到了给出具有固定总和的随机整数,但是如何对这些整数施加约束的方法。

Joh*_*man 2

我建议采用一种偶然的方法来保证满足约束的生成序列的均匀分布。很容易算出,{0,1,2}中的6个随机整数加起来为8的概率约为12.3%,因此在命中之前不需要太多的尝试。这是一个 Python 实现:

import random

def randNums(n,a,b,s):
    #finds n random ints in [a,b] with sum of s
    hit = False
    while not hit:
        total, count = 0,0
        nums = []
        while total < s and count < n:
            r = random.randint(a,b)
            total += r
            count += 1
            nums.append(r)
        if total == s and count == n: hit = True
    return nums
Run Code Online (Sandbox Code Playgroud)

这是 5 次运行的输出:

>>> for i in range(5): print(randNums(6,0,2,8))

[2, 1, 0, 2, 1, 2]
[0, 2, 2, 1, 1, 2]
[2, 2, 0, 2, 0, 2]
[2, 2, 0, 1, 1, 2]
[1, 2, 1, 1, 1, 2]
Run Code Online (Sandbox Code Playgroud)

编辑时:我对确切的概率感到好奇,因此编写了一个程序来详尽地枚举所有可能性。{0,1,2} 中长度为 6 的随机序列可以被认为是以 3 为基数编写的 0 到 3^6-1 = 728 中的随机整数。只需计算该范围内以 3 为基数的数字的数字和即可看到其中 = 8:

def toBase3(n):
    digits = []
    q,r = divmod(n,3)
    while q > 0:
        digits.append(r)
        q,r = divmod(q,3)
    digits.append(r)
    return ''.join(str(i) for i in reversed(digits))

def dsum(s):
    return sum(int(d) for d in s)

hits = []
for n in range(729):
    s = toBase3(n)
    if dsum(s) == 8: hits.append(s)

hits = [('0'*(6-len(s)))+s for s in hits] #left-pad with '0' if needed

s = ''.join(hits)

print("%d valid sequences for prob. of %f" % (len(hits),len(hits)/3.0**6))
print("%d zeros in those sequences for a prob. of %f" % (s.count('0'),s.count('0')/540.0))
print("%d ones in those sequences for a prob. of %f" % (s.count('1'),s.count('1')/540.0))
print("%d twos in those sequences for a prob. of %f" % (s.count('2'),s.count('2')/540.0))
Run Code Online (Sandbox Code Playgroud)

输出:

90 valid sequences for prob. of 0.123457
90 zeros in those sequences for a prob. of 0.166667
180 ones in those sequences for a prob. of 0.333333
270 twos in those sequences for a prob. of 0.500000
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这样一个长度为 6 的随机序列总和为 8(显示更多小数位)的概率为

90/729 = 0.123456790 (repeating)
Run Code Online (Sandbox Code Playgroud)

我没有意识到对令人愉悦的小数有如此好的概率解释0.1234567。可惜8之后就没有了7