优草派  >   Python

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

陈伟杰            来源:优草派

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

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

if prime[i]:

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

prime[j] = False

```

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

【原创声明】凡注明“来源:优草派”的文章,系本站原创,任何单位或个人未经本站书面授权不得转载、链接、转贴或以其他方式复制发表。否则,本站将依法追究其法律责任。
TOP 10
  • 周排行
  • 月排行