我写了一个素因子分解函数:
def prime_factorization(n):
prime_factors = {}
for i in _prime_candidates(n):
if n % i == 0:
prime_factors[i] = 0
while n % i == 0:
n /= i
prime_factors[i] += 1
if n != 1: prime_factors[int(n)] = 1
return prime_factors
def _prime_candidates(n):
yield 2
for i in range(3, int(n**.5)+1, 2):
yield i
在我的机器上n=10^13大约需要0.387秒。但是,如果我复制for循环的内容并在运行实际的for循环之前对数字2运行它,我会得到相同的正确结果,但是对于n=10^13,运行时间大约为0.003秒。您可以看到下面的代码:
def prime_factorization(n):
prime_factors = {}
if n % 2 == 0:
prime_factors[2] = 0
while n % 2 == 0:
n /= 2
prime_factors[2] += 1
for i in _prime_candidates(n):
if n % i == 0:
prime_factors[i] = 0
while n % i == 0:
n /= i
prime_factors[i] += 1
if n != 1: prime_factors[int(n)] = 1
return prime_factors
def _prime_candidates(n):
yield 2
for i in range(3, int(n**.5)+1, 2):
yield i
为什么这会导致如此巨大的性能提升?你知道吗
编辑:我使用的是python3.5,我使用的是clock()
模块的time
函数来进行基准测试。你知道吗
原因在
_prime_candidates
函数内部。 在您的第一个示例中,它生成所有的数字3,5,...,3162277
,您尝试用这些候选数除以n
。你知道吗在第二个例子中,首先大大减少
n
,这样_prime_candidates
生成数字3,5,...,34939
。要核对的数字要少得多。你知道吗在您的初始版本中,
_prime_candidates
通过10^13,因此它生成的候选者达到该值的平方根。你知道吗在您的第二个版本中,
_prime_candidates
通过了5^13,因为2的所有因子都被除掉了。它产生的候选者要少得多。你知道吗通过将
_prime_candidates
逻辑折叠成prime_factorization
并在找到因子时重新计算上界,可以得到更好、更一般的改进:注意,对于足够大的
n
,由于浮点精度的限制,n**.5
的计算最终会生成错误的界限。您可以通过比较candidate * candidate <= n
,或者使用decimal
模块之类的工具来计算绑定以达到足够的精度来解决这个问题。你知道吗相关问题 更多 >
编程相关推荐