2 回答
TA贡献1788条经验 获得超4个赞
choice需要一系列项目可供选择,而不是变量。包装参数以匿名或它将起作用,更改:tuplelist
value = r.choice(r.randint(10, 30), r.randint(50, 100))
更改为以下任一选项:
value = r.choice((r.randint(10, 30), r.randint(50, 100))) # Tuple
value = r.choice([r.randint(10, 30), r.randint(50, 100)]) # List
TA贡献1757条经验 获得超8个赞
随机选择接受单个序列。关于如何生成所需的数字,您有几个选择。
要修复即时错误,请将输入设置为序列:
value = r.choice([r.randint(10, 30), r.randint(50, 100)])
这不是一个很好的解决方案,因为它会生成两个数字,这是浪费的。此外,生成的分布以范围的大小为条件,这可能是不正确的。
解决此问题的更一般方法是生成单个数字并将其映射到所需的范围:
v = r.randint(0, 21 + 51)
value = v + 10 if v <= 20 else v - 21 + 50
如果要将输入指定为范围并在所有输入之间获得均匀分布,则可以像这样进行泛化:
def from_ranges(*ranges):
n = sum(map(len, ranges))
v = random.randrange(n)
for range in ranges:
k = len(range)
if v < k:
return range[v]
v -= k
这很好,因为范围是小对象,不占用太多空间,但在可以指定的内容方面允许您有很大的灵活性。
对于您问题中的示例,您可以将该函数称为
>>> from_ranges(range(10, 31), range(50, 101))
您还可以通过将长度累积为累积总和来消除最终的线性搜索,以支持二进制搜索:
from bisect import bisect
from itertools import accumulate
from random import randrange
def from_ranges(*ranges):
lengths = list(accumulate(map(len, ranges)))
v = randrange(lengths[-1])
r = bisect(lengths, v)
offset = lengths[r - 1] if r > 0 else 0
return ranges[r][v - offset]
如果要在生成随机数之前记住累积,则此解决方案会更快。否则,与第一种解决方案相比,它几乎没有优势。
添加回答
举报