Python 有人能解释为什么这种寻找素数的方法比我的快得多吗?
我几天前才开始编程,试图解决一个涉及大量素数的问题。下面是我提出的方法,但是对于大量的数据,它的速度很慢:Python 有人能解释为什么这种寻找素数的方法比我的快得多吗?,python,time,process,generator,primes,Python,Time,Process,Generator,Primes,我几天前才开始编程,试图解决一个涉及大量素数的问题。下面是我提出的方法,但是对于大量的数据,它的速度很慢: import time import math t0=time.clock() a=100000 ##preprimes is the list of primes up to sqrt(a) that will be ##divided into the larger list lista preprimes=[] lista= list(range(1,a)) prelis
import time
import math
t0=time.clock()
a=100000
##preprimes is the list of primes up to sqrt(a) that will be
##divided into the larger list lista
preprimes=[]
lista= list(range(1,a))
prelista= list(range(1,round(math.sqrt(a))))
def predivisors(a):
x=a-1
suma=0
while (x>0):
if a%x==0:
suma=suma+x
x=x-1
if suma==1:
preprimes.append(a)
else:
x=x-1
for x in prelista:
predivisors(x)
for n in preprimes:
for num in lista:
if num%n==0:
lista.remove(num)
print(sum(lista)+sum(preprimes)-1 )
print(time.clock()-t0, ' seconds')
此方法需要81秒才能返回多达10万个素数的总和。我在网上找到的以下方法对于同一任务需要0.38秒:
import math
import time
t0=time.clock()
n=100000
def getPrimes(n):
"""returns set of all primes below n"""
non_primes = [j for j in range(4, n, 2)] # 2 covers all even numbers
for i in range(3, n, 2):
non_primes.extend([j for j in range(i*2, n, i)])
return set([i for i in range(2, n)]) - set(non_primes)
def getCircularPrimes(n):
primes = getPrimes(n)
is_circ = []
for prime in primes:
prime_str = str(prime)
iter_count = len(prime_str) - 1
rotated_num = []
while iter_count > 0:
prime_str = prime_str[1:] + prime_str[:1]
rotated_num.append(int(prime_str))
iter_count -= 1
if primes >= set(rotated_num):
is_circ.append(prime)
return len(is_circ)
print(sum(getPrimes(n)))
##print(sorted(getPrimes(n)))
print('process took ',time.clock()-t0,'seconds')
为什么第二种方法比我的快那么多?什么因素决定了一个过程需要多长时间?在您的方法中,您根据
n
对一个n
数字列表与另一个基于n
的大型数字列表进行评估。
在这样做的过程中,你会执行大量的任务
for n in preprimes:
for num in lista:
if num%n==0:
lista.remove(num)
我相信这将导致时间复杂度在O(n^2)
范围内
看
在在线方法中,我认为它的复杂性更接近于O(n)
随着输入的增加,
O(n)
和O(n^2)
在运行时的差异急剧增加。我相信第二种方法是使用埃拉托斯的seive(sp?),这几乎是计算我发现的素数的最快方法(至少我可以实现)顺便提一下,这里有一个简单的技巧---->isPrime=lambda n:~-2**n%n==1
请注意,getCircularTimes
函数是一个令人费解的问题,它不在任何地方调用,也不用于素数的计算。我想这是因为你的remove函数。当你在删除一个元素后使用该函数时,之后的所有其他元素都会被移动,这需要时间。不确定这是否明显是dup,但问题是相同的:我们已经实现了试用划分,实现了Eratosthenes筛选,还有一个问题,为什么前者在算法上比后者慢。其他一切在这里都无关紧要。但前提是你真的知道如何阅读代码。我认为这意味着,如果这不是dup,那么这不是SO的问题,属于另一个SE站点,但我很容易被说服。@JoranBeasley:筛子绝对不是计算素数的最快方法。对于巨大的素数,有更好的算法(上面提到了一些)。当然,对于较小的素数,一个查找表(或一个N**.25的轮子)是最好的解决方案你能简单解释一下在线代码中getPrimes(n)函数是如何工作的吗?