[英]How do I optimize my Python code to perform my calculation using less memory?
I have put together the following code in order to determine if a number has an odd or even number of divisors. 我将以下代码组合在一起,以确定一个数的除数是奇数还是偶数。 The code works well with relatively small numbers but once a larger number like 9 digits is entered it hangs up.
该代码适用于相对较小的数字,但是一旦输入较大的数字(如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'
what can I do to make this more efficient? 我该怎么做才能提高效率?
Here's your problem: 这是您的问题:
num = len(set([x for x in range(1,n+1) if not divmod(n,x)[1]]))
This constructs a list, then constructs a set out of that list, then takes the length of the set. 这将构造一个列表,然后从该列表中构造一个集合,然后获取集合的长度。 You don't need to do any of that work (
range()
, or xrange()
for that matter, does not produce repeated objects, so we don't need the set, and sum()
works on any iterable object, so you don't need the list either). 您不需要做任何工作(
range()
或xrange()
都不会产生重复的对象,因此我们不需要set,并且sum()
可在任何可迭代的对象上使用,因此您也不需要该列表)。 While we're on the subject, divmod(n, x)[1]
is just a very elaborate way of writing n % x
, and consumes a little bit of extra memory to construct a tuple (which is immediately reclaimed because you throw the tuple away). 当我们讨论这个主题时,
divmod(n, x)[1]
只是编写n % x
一种非常复杂的方法,并且会消耗一点额外的内存来构造一个元组(由于您抛出了元组)。 Here's the fixed version: 这是固定版本:
num = sum(1 for x in xrange(1,n+1) if not n % x)
You do not need to test every possible divisor, testing up to sqrt(n) is enough. 您无需测试所有可能的除数,最多测试sqrt(n)就足够了。 This will make your function O(sqrt(n)) instead of O(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
In my benchmarks using python2 this is 1000 times faster than sum(1 for x in range(1, n + 1) if not n % x)
with n = int(1e6)
and 10000 times faster for 1e8. 在我使用python2的基准测试中,这比
sum(1 for x in range(1, n + 1) if not n % x)
快1000倍,而sum(1 for x in range(1, n + 1) if not n % x)
n = int(1e6)
比1e8快10000倍。 For 1e9
the latter code gave me a memory error , suggesting that the whole sequence is stored in memory before doing the sum because in python 2 range()
returns a list and I should be using xrange()
instead. 对于
1e9
,后面的代码给了我一个内存错误,这表明整个序列在进行求和之前先存储在内存中,因为在python 2中range()
返回一个列表,而我应该使用xrange()
。 For python3 range()
is fine. 对于python3,
range()
很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.