我对python比较陌生,我对两个相对简单的代码块的性能感到困惑。第一个函数在给定素数列表的情况下生成数n的素数因子分解。第二个生成n的所有因子的列表。我会prime_factor
比factors
更快(对于相同的n),但事实并非如此。我不是在寻找更好的算法,而是希望了解prime_factor
为什么比factors
慢得多。
def prime_factor(n, primes):
prime_factors = []
i = 0
while n != 1:
if n % primes[i] == 0:
factor = primes[i]
prime_factors.append(factor)
n = n // factor
else: i += 1
return prime_factors
import math
def factors(n):
if n == 0: return []
factors = {1, n}
for i in range(2, math.floor(n ** (1/2)) + 1):
if n % i == 0:
factors.add(i)
factors.add(n // i)
return list(factors)
使用timeit模块,
{ i:factors(i) for i in range(1, 10000) }
需要2.5秒
{ i:prime_factor(i, primes) for i in range(1, 10000) }
需要17秒
这对我来说很惊讶。 factors
检查从1到sqrt(n)的每个数字,而prime_factor
仅检查素数。在理解这两个功能的性能特征时,我将不胜感激。
由于
编辑:(对roliu的回应)
这是我的代码,用于生成从2到up_to
的素数列表:
def primes_up_to(up_to):
marked = [0] * up_to
value = 3
s = 2
primes = [2]
while value < up_to:
if marked[value] == 0:
primes.append(value)
i = value
while i < up_to:
marked[i] = 1
i += value
value += 2
return primes
答案 0 :(得分:12)
如果没有看到您用于primes
的内容,我们必须猜测(我们无法运行您的代码)。
但其中很大一部分只是数学:有(非常粗略地说)关于n/log(n)
素数小于n
,并且比sqrt(n)
大很多。因此,当您通过素数时,prime_factor(n)
会做更多工作:在找到第一个素数因子(O(n/log(n))
本身!)之前,它会经过n
次操作,而factors(n)
给出在O(sqrt(n))
次操作之后。
这可能非常重要。例如,sqrt(10000)
只有100,但有1229个素数小于10000.所以prime_factor(n)
可以需要做10倍以上的工作来处理大素数在你的范围内。