如何生成6个随机整数,它们的总和为8,每个整数均小于或等于2?
例如。1,2,1,2,2,0
到目前为止,我已经找到了给出具有固定总和的随机整数,但是如何对这些整数施加约束的方法。
我建议采用一种偶然的方法来保证满足约束的生成序列的均匀分布。很容易算出,{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。