提高大型彩票模拟的效率

时间:2017-06-21 00:37:41

标签: python performance python-2.7

我创建了一个python彩票模拟器,它可以生成一个由0-75组成的5个随机数的数组('中奖号码'):

    for n in xrange(0, 5):
    winning_number.append(randint(0, 75))
然后,它会检查用户定义的票数' ('计数'变量)对抗'胜利'阵列。

while count > 0:
    for n in xrange(0, 5):
        result.append(randint(0, 75))
    if result == winning_number:
        wingame += 1
        count -= 1
        del result[:]
    else:
        count -= 1
        del result[:]

正如预期的那样,大约1000万以上的计数值开始花费很长时间并开始对我的系统资源征税,但我真的想要运行更大的计数值。我是否有任何修改可以帮助避免多余的步骤?使用像PyCUDA或pyOpenCl这样的东西会有效和/或在编码新手的范围内吗?

我感谢您提供的任何帮助或您可以指出的资源。谢谢!

1 个答案:

答案 0 :(得分:1)

你的彩票数学有点奇怪;

首先,random.randint(0, 75)生成包含两个端点的值 - 因此您要从76个值(0 ... 75)中进行选择。也许你的意思是(1, 75)

其次,您允许重复的值,即3, 3, 3, 3, 3是有效的票证。彩票通常不允许重复。请查看random.sample,即random.sample(range(1, 76), 5)

第三,您选择值的顺序显然很重要 - 1, 2, 3, 4, 51, 3, 2, 4, 5不同。彩票通常不考虑订单(除了可能的奖金号码)。在Python术语中,您应该比较集而不是列表。

第四,实际生成值列表涉及大量分配和释放内存;通过操作枚举状态而不是实际生成每个状态,可以更便宜地获得相同的效果。例如,您可以说{1, 4, 7, 19, 21}是百万分之一和第三组合,然后测试randvalue == 1000003而不是randset == {1, 4, 7, 19, 21}

实施这些更改,您可以简化逻辑,如

from random import randrange
from math import factorial

VALUES = 75
PICKS = 5
TICKETS = 10000000

# calculate number of unique tickets
num_combos = factorial(VALUES) // (factorial(VALUES - PICKS) * factorial(PICKS))

winner = randrange(num_combos)
num_winners = sum(randrange(num_combos) == winner for _ in range(TICKETS))

编辑:快速思考并测试了它;

num_winners = sum(1 for _ in range(TICKETS) if randrange(num_combos) == winner)

快5%左右。 (超过85%的运行时现在只用于生成随机值。)

Edit2:另一个想法 - 如果我们任意说“0是获胜状态”,那么我们的主循环变为

num_winners = sum(1 for _ in range(TICKETS) if not randrange(num_combos))

再加快2.5%。

或者你可以直接进入最终解决方案,

from numpy.random import poisson

num_winners = poisson(TICKETS / num_combos)