如何用python求100以内的素数?

素数是指只能被1和本身整除的正整数,比如2、3、5、7、11、13等。求100以内的素数是一个经典的问题,也是程序员入门时常见的练手题。下面我们将从多个角度分析如何用python求100以内的素数。

方法一:暴力枚举

最直接的想法是对每个数进行判断,看它是否能被1和本身以外的数整除。代码如下:

```python

for i in range(2,101):

flag = True

for j in range(2,i):

if i % j == 0:

flag = False

break

if flag:

print(i)

```

这种方法的时间复杂度为O(n^2),对于100以内的数来说还比较快。但如果我们要求更大范围内的素数,这种方法就变得相当低效了。

方法二:埃氏筛法

埃氏筛法是一种经典的素数筛法,可以在O(nloglogn)的时间复杂度内求出n以内的素数。其基本思想是:从2开始,将每个质数的倍数都标记成合数,直到筛完所有小于等于n的数。代码如下:

```python

def eratosthenes(n):

prime = [True] * (n + 1)

prime[0] = prime[1] = False

for i in range(2,int(n ** 0.5) + 1):

if prime[i]:

for j in range(i * i,n + 1,i):

prime[j] = False

return [i for i in range(n + 1) if prime[i]]

```

这段代码首先生成一个长度为n+1的布尔数组prime,其中prime[i]表示i是否为素数。然后从2开始,找到第一个素数p,将p的所有倍数都标记成合数,即prime[P*p],prime[P*p+p],prime[P*p+2p],...都设为False。接着找下一个素数,重复上述操作,直到筛完所有小于等于n的数。最后返回所有为素数的数。

方法三:欧拉筛法

欧拉筛法是一种优化的素数筛法,可以在O(n)的时间复杂度内求出n以内的素数。其基本思想是:对每个数只筛掉它最小的质因子,避免重复标记代码如下:

```python

def euler(n):

prime = []

vis = [False] * (n + 1)

for i in range(2,n + 1):

if not vis[i]:

prime.append(i)

for j in range(len(prime)):

t = i * prime[j]

if t > n:

break

vis[t] = True

if i % prime[j] == 0:

break

return prime

```

这段代码首先生成一个空列表prime和一个长度为n+1的布尔数组vis,其中vis[i]表示i是否被筛掉了。接着从2开始遍历每个数,如果它没有被筛掉,说明它是素数,将其加入prime列表中。然后遍历prime列表中的每个质数,将当前数与质数的乘积标记成合数,同时判断如果当前数能被质数整除,就可以停止遍历质数列表了。

方法四:numpy优化

numpy是python中常用的数值计算库,它的数组操作比python原生的列表更快。我们可以用numpy数组来实现埃氏筛法,从而进一步提高效率。代码如下:

```python

import numpy as np

def eratosthenes_np(n):

prime = np.ones(n + 1,dtype=bool)

prime[0] = prime[1] = False

for i in range(2,int(n ** 0.5) + 1):

if prime[i]:

prime[i * i: n + 1: i] = False

return np.where(prime)[0]

```

这段代码首先生成一个长度为n+1的numpy布尔数组prime,其中prime[i]表示i是否为素数。然后从2开始,找到第一个素数p,将p的所有倍数都标记成合数,即prime[P*p:n+1:p]都设为False。这里用到了numpy数组的切片和步长操作,可以一次性标记多个数。最后返回所有为素数的数。

方法五:多线程优化

我们可以用多线程来优化素数筛法,将筛数的任务分给多个线程同时处理,可以大大提高效率。代码如下:

```python

import threading

def eratosthenes_mt(n,num_threads=4):

prime = [True] * (n + 1)

prime[0] = prime[1] = False

threads = []

for i in range(num_threads):

t = threading.Thread(target=eratosthenes_mt_worker,args=(i,num_threads,n,prime))

threads.append(t)

t.start()

for t in threads:

t.join()

return [i for i in range(n + 1) if prime[i]]

def eratosthenes_mt_worker(start,step,prime):

for i in range(start + 2,step):

if prime[i]:

for j in range(i * i,i):

prime[j] = False

```

这段代码首先生成一个长度为n+1的列表prime,其中prime[i]表示i是否为素数。然后创建num_threads个线程,每个线程负责筛掉start+2,start+2+step,start+2+2*step,...等数中的合数。最后等待所有线程执行完毕,返回所有为素数的数。

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...