我正试图找到一个数字的最大素数因子。当使用较小的数字时,代码在IDLE上正确运行,但是当我将更大的数字(如600851475143)分配给n时,似乎根本不会在屏幕上打印任何内容。为什么呢?
def isPrime(n):
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
顺便说一下,我正在运行Python 3.3。
=============================================== ===============================
谢谢大家!
我修改了原始代码如下:
def isPrime(n):
for i in range(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
if i == n:
break
n = n / i
print("The largest prime factor is", largest)
像nakedfanatic所说,他们的代码运行得更快,我稍微编辑了一下:
largest = 0
n = 600851475143
i = 2
while True:
if n % i == 0:
largest = i
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", largest)
答案 0 :(得分:2)
有几个优化领域:
所有因素分解只需要达到sqrt(n)
(含)
将isPrime()
转换为表格查找
使用n
初始化查找表,然后只计算一次所有素数< sqrt(n)
并循环遍历它们。
正如评论所指出的,这会占用大量内存空间。我们可以使用位标志将内存需求减少到1/8,如果我们跳过所有偶数,我们可以将它减少一半(然后必须测试n是否是单独的)。但对于LARGE n
来说,这可能仍然令人生畏。
(如果使用当前代码)在isPrime()
早期返回(由@justhalf提供)
向后循环(从sqrt(n)
到2)
如果在除以因子之后商数为1时提前返回(由@justhalf提供)
这篇文章(@prashant建议)包含更复杂的算法(使我的建议非常天真&gt;&lt;):
...(欢迎编辑)
答案 1 :(得分:1)
最有可能的是,您的代码并没有以大n
为终结,只是因为在循环中运行需要很长时间。
答案 2 :(得分:1)
这是因为即使n
已经为1,您也会继续尝试。
此代码将帮助您查看问题:
def isPrime(n):
for i in xrange(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in xrange(2,n-1):
print 'Checking whether %d divides %d' % (i,n)
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
将产生:
... Checking whether 6857 divides 6857 Checking whether 6858 divides 1 Checking whether 6859 divides 1 Checking whether 6860 divides 1 Checking whether 6861 divides 1 Checking whether 6862 divides 1 Checking whether 6863 divides 1 Checking whether 6864 divides 1 Checking whether 6865 divides 1 Checking whether 6866 divides 1 Checking whether 6867 divides 1 Checking whether 6868 divides 1 Checking whether 6869 divides 1 Checking whether 6870 divides 1 Checking whether 6871 divides 1 Checking whether 6872 divides 1 Checking whether 6873 divides 1 ...
当n
变为1时,你应该打破循环,这样它就不会进行不必要的检查
n = n / i
if n==1:
break
continue
无论如何,你的代码可能会有很多改进,哈哈,看看别人的建议。
答案 3 :(得分:1)
您的代码在O(n²)时间内运行,这意味着随着n的大小增加,它将很快变得非常慢。这就是为什么你的算法适用于较小的值,但挂起的值很大。
此代码在O(n)时间内完成相同的操作而根本不进行任何质数检查,并立即返回结果:
prime_factors = []
n = 600851475143
i = 2
while True:
if n % i == 0:
prime_factors.append(i)
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", prime_factors[-1])
答案 4 :(得分:1)
更困难的问题可能需要不同的算法。
请检查此问题:Fastest way to list all primes below N
您的代码看起来不错,但对于大型n
可能需要很长时间。利用数学可以使您更快地完成这个问题。
在该链接上,我推荐rwh_primes1
用于纯python解决方案,primesfrom3to
用作使用numpy的解决方案。这两个实现都相当简短,相对清晰,基本上做同样的事情。这些代码片段是用Python 2编写的,因此翻译可能如下所示:
def rwh_primes1(n):
sieve = [True] * (n//2)
for i in range(3, int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in range(1,n//2) if sieve[i]]
答案 5 :(得分:0)
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
由于无条件return
,此循环始终退出第一次迭代。尝试:
for i in range(2,n-1):
if n % i == 0:
return False
return True
此外,上限n-1
可以缩减为sqrt(n)+1
。
答案 6 :(得分:0)
代码的另一个方面可能会减慢代码的下半部分
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
特别是声明
if isPrime(i) and n % i == 0:
根据documentation,仅在第一个条件为True
时评估第二个条件。在你的情况下,反转条件会更有意义,因此总是执行计算成本较低的除法,而更昂贵的isPrime()
仅用于实际因子
largest = 0
n = 600851475143
for i in range(2,n-1):
if n % i == 0 and isPrime(i):
largest = i
n = n / i
if n == 1:
break