Python 素数查找函数的优化
经过10分钟的工作,我写了一个函数如下。它返回比参数低的所有素数的列表。为了使这个函数尽可能快,我使用了所有为我所知的编程和数学技巧。要找到所有低于一百万的素数,大约需要2秒钟 你认为有可能进一步优化它吗?有什么想法吗Python 素数查找函数的优化,python,primes,Python,Primes,经过10分钟的工作,我写了一个函数如下。它返回比参数低的所有素数的列表。为了使这个函数尽可能快,我使用了所有为我所知的编程和数学技巧。要找到所有低于一百万的素数,大约需要2秒钟 你认为有可能进一步优化它吗?有什么想法吗 def Primes(To): if To<2: return [] if To<3: return [2] Found=[2] n=3 LastSqr=0 while n<=To: k=0 Limit
def Primes(To):
if To<2:
return []
if To<3:
return [2]
Found=[2]
n=3
LastSqr=0
while n<=To:
k=0
Limit=len(Found)
IsPrime=True
while k<Limit:
if k>=LastSqr:
if Found[k]>pow(n,0.5):
LastSqr=k
break
if n%Found[k]==0:
IsPrime=False
break
k+=1
if IsPrime:
Found.append(n)
n+=1
return Found
def预充(至):
如果你想通过谷歌和维基百科找到更好的算法。如果你只寻找小的素数,这可能足够快了。但是真正的算法对于大素数要快得多
从那一页开始
将n增加2而不是1 谷歌和维基百科寻找更好的算法。如果你只寻找小的素数,这可能足够快了。但是真正的算法对于大素数要快得多
从那一页开始
将n增加2而不是1 您只能检查奇数。那么为什么不使用n+=2而不是n+=1呢?您只能检查奇数。那么,为什么不使用n+=2而不是n+=1呢?您可以使用一些技巧来加快速度,使用erastothenes的基本筛选。一种是用来跳过计算已知不是素数的数。例如,除了2和3之外,所有素数都与1或5模6全等。这意味着您根本不需要处理每6个数字中的4个
在下一个层次上,所有素数都与1、7、11、13、17、19、23或29,mod 30全等。每30个数字中,你可以扔掉22个
下面是一个简单的Erastothenes筛选实现,它不计算或存储偶数:
def basic_gen_primes(n):
"""Return a list of all primes less then or equal to n"""
if n < 2:
return []
# The sieve. Each entry i represents (2i + 1)
size = (n + 1) // 2
sieve = [True] * size
# 2(0) + 1 == 1 is not prime
sieve[0] = False
for i, value in enumerate(sieve):
if not value:
continue
p = 2*i + 1
# p is prime. Remove all of its multiples from the sieve
# p^2 == (2i + 1)(2i + 1) == (4i^2 + 4i + 1) == 2(2i^2 + 2i) + 1
multiple = 2 * i * i + 2 * i
if multiple >= size:
break
while multiple < size:
sieve[multiple] = False
multiple += p
return [2] + [2*i+1 for i, value in enumerate(sieve) if value]
def basic\u gen\u prime(n):
“”“返回小于或等于n的所有素数的列表”“”
如果n<2:
返回[]
#筛子。每个条目i表示(2i+1)
大小=(n+1)//2
筛子=[真实]*尺寸
#2(0)+1==1不是素数
筛[0]=假
对于i,枚举(筛)中的值:
如果不是值:
持续
p=2*i+1
#p是素数。从筛子上去除所有的倍数
#p^2==(2i+1)(2i+1)==(4i^2+4i+1)==2(2i^2+2i)+1
倍数=2*i*i+2*i
如果多个>=大小:
打破
而多个<大小:
筛选[多个]=错误
多重+=p
返回[2]+[2*i+1表示i,枚举(筛选)中的值如果值]
如前所述,您还可以使用更多的奇异筛。您可以使用erastothenes的基本筛,使用一些技巧来加快速度。一种是用来跳过计算已知不是素数的数。例如,除了2和3之外,所有素数都与1或5模6全等。这意味着您根本不需要处理每6个数字中的4个
在下一个层次上,所有素数都与1、7、11、13、17、19、23或29,mod 30全等。每30个数字中,你可以扔掉22个
下面是一个简单的Erastothenes筛选实现,它不计算或存储偶数:
def basic_gen_primes(n):
"""Return a list of all primes less then or equal to n"""
if n < 2:
return []
# The sieve. Each entry i represents (2i + 1)
size = (n + 1) // 2
sieve = [True] * size
# 2(0) + 1 == 1 is not prime
sieve[0] = False
for i, value in enumerate(sieve):
if not value:
continue
p = 2*i + 1
# p is prime. Remove all of its multiples from the sieve
# p^2 == (2i + 1)(2i + 1) == (4i^2 + 4i + 1) == 2(2i^2 + 2i) + 1
multiple = 2 * i * i + 2 * i
if multiple >= size:
break
while multiple < size:
sieve[multiple] = False
multiple += p
return [2] + [2*i+1 for i, value in enumerate(sieve) if value]
def basic\u gen\u prime(n):
“”“返回小于或等于n的所有素数的列表”“”
如果n<2:
返回[]
#筛子。每个条目i表示(2i+1)
大小=(n+1)//2
筛子=[真实]*尺寸
#2(0)+1==1不是素数
筛[0]=假
对于i,枚举(筛)中的值:
如果不是值:
持续
p=2*i+1
#p是素数。从筛子上去除所有的倍数
#p^2==(2i+1)(2i+1)==(4i^2+4i+1)==2(2i^2+2i)+1
倍数=2*i*i+2*i
如果多个>=大小:
打破
而多个<大小:
筛选[多个]=错误
多重+=p
返回[2]+[2*i+1表示i,枚举(筛选)中的值如果值]
如前所述,你也可以使用更奇特的筛子。我猜sqrt(n)
比pow(n,0.5)
快。
请看一个带有时间的快速测试,它证实,sqrt(n)
确实比pow(n,0.5)快
@user1354439请查看有关标识符名称的信息,例如局部变量。我猜sqrt(n)
比pow(n,0.5)快。
请看一个时间快速测试,它确认,sqrt(n)
确实比pow(n,0.5)快
@user1354439请查看有关标识符名称(如局部变量)的信息。好主意:)我将检查它是否缩短了执行时间,谢谢您将执行时间增加6次,每次迭代中检查n-1
和n+1
可能会更快。通过跳过三的倍数来优化埃拉托斯烯的筛分也是一个常见的技巧。(但从未在Python中尝试过。)好主意:)我会检查它是否缩短了执行时间,谢谢你,增加6次,每次迭代中检查n-1
和n+1
可能会更快。通过跳过三的倍数来优化埃拉托斯烯的筛分也是一个常见的技巧。(但从未在Python中尝试过。)2*i*i+2*i==2*i*(i+1)
。这一事实值得强调的是,这里的代码是Eratosthenes的筛子,因此在正确实现的情况下,应该总是比OP这样的试用除法代码快得多。2*i*i+2*i==2*i*(i+1)
。这一事实值得强调的是,这里的代码是Eratosthenes的筛子,因此在正确实现时,应该比OP这样的试算代码快得多。