我想模拟一下你必须多久玩一次彩票才能中奖:
import random
lotterylist = [random.randint(1, 49) for x in range(6)]
winning_numbers = [6, 26, 31, 32, 33, 49]
counter = 0
while winning_numbers != lotterylist:
lotterylist = [random.randint(1, 49) for x in range(6)]
counter += 1
print("Finished! I got", counter, "tries to win.")
我运行了该程序 1.5 小时,它仍然运行。是否仅当生成的列表中的数字也位于完全相同的行时才有效,因此只有 6、26、31、32、33、49 才有效,而 49、33、32、31、26、6 无效?如果是的话,我该如何解决这个问题?
“仅当生成的列表中的数字也位于完全相同的行时才有效吗?”
是的。
winning_numbers
和 lotterylist
都是 list
数据类型,并且列表在 Python 中是有序的。
如果您不希望顺序重要,您可以使用
set
winning_numbers = {6, 26, 31, 32, 33, 49} # set type
winning_numbers = set(6, 26, 31, 32, 33, 49) # equivalent to the above
# demonstrating "set" behavior
assert winning_numbers == {49, 26, 32, 31, 33, 6} # True
请注意,
set
不能/不包含重复元素。这意味着如果在推导式中生成两次相同的数字,则以下代码可能会出现错误,有时 lotterylist
的数字少于 6 个:
while winning_numbers != lotterylist:
lotterylist = {random.randint(1, 49) for x in range(6)} # no good
最好的(最简单且执行最快)方法是使用
random.sample
,它从群体中选择 k
独特的值:
lotterylist = set(random.sample(range(1,50), k=6))
数字
[1, 49]
的有序 6 位数字序列的数量为 496 或 13841287201,因此六个数字随机匹配一个特定序列的机会为 1/13841287201。给定一个以 p
概率发生的事件,直到该事件发生之前预期的试验次数 E
被简单地定义为 E=1/p
——在本例中为 E = 13,841,287,201
(非常简单)。这意味着您的循环在中奖之前可能会运行大约 140 亿次。
为了了解这可能需要多长时间,我对以下代码进行了计时:
start_time = time.time()
counter = 13_800_000 # 13.8 million iterations
while lotterylist != [1,2,3]:
lotterylist = [random.randint(1, 49) for x in range(6)]
counter -= 1
if not counter:
break
print(time.time() - start_time)
在我的机器上完成这么多次迭代花了 22 秒;这意味着 138 亿次迭代大约需要 6 小时,具体时间取决于您的计算机和运气。
我们对中奖可能性的总数感兴趣,因为这决定了中奖之前预期的尝试次数
E
(您玩彩票的次数)。我们将 n 定义为每个值的可能性数量(n=49
您的情况),将 k 定义为样本数量 (k=6
)。
如果中奖号码的顺序确实重要并且数字可以出现多次(如使用列表的原始代码中),这称为抽样与替换,并且可能性的总数为nk = 13,841,287,201 和 E=13,841,287,201
。如果顺序无关紧要,并且每个数字只能出现一次,这称为
无替换采样,因为一旦选择了一个值就无法再次选择。对于无放回抽样,总计定义为 n 选择 k,或 C(n, k)
,其公式为二项式系数。插入n 和 k 给出了 13983816 个组合,因此在
E=13,983,816
成功之前进行了预期的试验次数
这意味着... 您根本不需要为彩票创建模拟。概率公式可以为您提供精确值,而模拟只能提供近似值。我已经给了你答案——如果你有一台超级计算机并运行原始代码一百万次并取计数器所有值的平均值,结果将非常接近 13,841,287,201。
为了演示这一点,我实现了六个数字的代码,其中顺序并不重要:
winning_numbers = {6, 26, 31, 32, 33, 49}
tot_count = 0
for i in range(5):
counter = 0
while winning_numbers != set(random.sample(range(1, 50), k=6)):
counter += 1
print(f"Attempt {i}: It took {counter} tries to win the lottery")
tot_count += counter
print(f"It took an average of {tot_count/5} tries to win")
经过 5 次抽奖,我每次中奖的平均次数为 11,752,990 次——非常接近估计的 13,983,816 次。如果我继续运行它,它会继续变得更接近。
所以只有 6, 26, 31, 32, 33, 49 有效,而不是 49, 33, 32, 31, 26, 6?正如其他答案所提到的,
while winning_numbers != lotterylist
行将在不同位置使用完全相同的整数执行。所以,是的,
winning_numbers
和
lotterylist
列表中的数字必须按精确顺序排列;如果顺序不重要,请使用集合。
如果是,我该如何解决?老实说,我认为您处理代码逻辑的方式存在问题。除了使用列表数据类型之外,您的代码还存在包含重复数字的风险(如上所述)。
我会找出你想要完成的不同任务,然后将你的代码分成单独的块来实现所述任务(这似乎是创建两组 6 个唯一整数并检查它们是否相等)。
对于初学者,请参阅: