【问题标题】:How do I optimize my Python code to perform my calculation using less memory?如何优化我的 Python 代码以使用更少的内存来执行我的计算?
【发布时间】:2016-04-08 04:27:47
【问题描述】:

我将以下代码放在一起以确定一个数字是否具有奇数或偶数除数。该代码适用于相对较小的数字,但一旦输入较大的数字(如 9 位),它就会挂断。

def divisors(n):
    num = len(set([x for x in range(1,n+1) if not divmod(n,x)[1]]))
    if (num != 0 and num % 2 == 0):
        return 'even'
    else:
        return 'odd'

我能做些什么来提高效率?

【问题讨论】:

标签: python math optimization numbers


【解决方案1】:

这是你的问题:

num = len(set([x for x in range(1,n+1) if not divmod(n,x)[1]]))

这会构造一个列表,然后从该列表中构造一个集合,然后获取集合的长度。你不需要做任何这些工作(range()xrange() 不会产生重复的对象,所以我们不需要集合,sum() 可以处理任何可迭代的对象,所以您也不需要列表)。当我们讨论这个主题时,divmod(n, x)[1] 只是编写n % x 的一种非常精细的方式,并且会消耗一点额外的内存来构造一个元组(因为你把元组扔掉了,所以它会立即被回收)。这是固定版本:

num = sum(1 for x in xrange(1,n+1) if not n % x)

【讨论】:

    【解决方案2】:

    你不需要测试每一个可能的除数,测试到 sqrt(n) 就足够了。这将使您的函数 O(sqrt(n)) 而不是 O(n)。

    import math
    
    def num_divisors(n):
        sqrt = math.sqrt(n)
        upper = int(sqrt)
        num = sum(1 for x in range(1, upper + 1) if not n % x)
        num *= 2
        if upper == sqrt and num != 0:
            num -= 1
        return num
    

    在我使用 python2 的基准测试中,这比使用 n = int(1e6)sum(1 for x in range(1, n + 1) if not n % x) 快 1000 倍,对于 1e8 快 10000 倍。对于1e9,后一个代码给了我一个内存错误,表明整个序列在进行求和之前存储在内存中,因为在python 2中range()返回一个列表,我应该使用@987654326 @ 反而。对于 python3 range() 很好。

    【讨论】:

    • 感谢您提醒我使用xrange() 而不是range()
    猜你喜欢
    • 2011-06-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多