python寻找n以内的素数算法

本文所利用的素数性质是:所有的素数都是奇数,且除2,3外其余素数都出现在6n-1与6n+1这两个数列中
具体代码如下
首先创建一个长度为n的false列表,再将索引为2,3,和6n+1、6n-1这两个数列在列表中的值改为True

L = [False]*N
L[2]=L[3]=True
L[5:N:6] = [True]*len(L[5:N:6])#数列6n-1
L[7:N:6] = [True]*len(L[7:N:6])#数列6n+1

这两数列中除了包含素数外还有一些非素数,所以我们需要想办法将那些非素数对应的值改为false
6n-1 : 5 11 17 23 29 35 41 47 53 59……
6n+1: 7 13 19 25 31 37 43 49 55 61……
不难发现这些数字都是前面那些素数的倍数,所以可以建立循环删除倍数

for i in range(5,int(N**0.5)+1,6):
    if L[i]:
       L[i*i:N:2*i] = [False]*len(L[i*i:N:2*i])#删除倍数
for i in range(7,int(N**0.5)+1,6):
    if L[i]:
        L[i*i:N:2*i] = [False]*len(L[i*i:N:2*i])#删除倍数

删除倍数这里 L[ii:N:2i],从i的i倍开始,而不是从i的1倍开始,原因是i的j倍(j<i)已经在前面删除过了,如果再删除就会重复工作;间隔为2*i的原因是,因为6n+1与6n-1这两个数列中只存在i的奇数倍,所以我们只需要删除i的奇数倍就好。

进行完上述工作,我们的列表L就成功记录到了N以内所有的素数,我们只需要利用一个循环将值为TRUE的索引读出来就好了

primes = []
for i in range(N):
    if L[i]:primes.append(i)

下面是整个代码

#!/bin/env python
#-*-coding:utf-8-*-

import time

def prime(N):
    L = [False]*N
    primes = []
    L[2]=L[3]=True
    L[5:N:6] = [True]*len(L[5:N:6])#数列6n-1
    L[7:N:6] = [True]*len(L[7:N:6])#数列6n+1
    for i in range(5,int(N**0.5)+1,6):
        if L[i]:
            L[i*i:N:2*i] = [False]*len(L[i*i:N:2*i])#删除倍数
    for i in range(7,int(N**0.5)+1,6):
        if L[i]:
            L[i*i:N:2*i] = [False]*len(L[i*i:N:2*i])#删除倍数
    for i in range(N):
        if L[i]:primes.append(i)
    return primes
if __name__=='__main__':
    t0=time.time()
    N = 10000001
    primes = prime(N)
    #print(primes)
    print('共找出%d个素数'%len(primes))
    runtime=time.time()-t0
    print('运行时间为',runtime, sep='')

程序运行截图:在这里插入图片描述
查找10000000以内的素数用时约两秒,还算可以。但感觉还有改进空间,在删除倍数那里,只删除奇数倍实际上还是有不必要的工作的,因为不是所有的奇数倍都在6n-1和6n+1这两个数列中。

如果有什么不懂的地方或者有什么改进的建议,欢迎留言!

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值