鱼C论坛

 找回密码
 立即注册
查看: 3111|回复: 5

[技术交流] 欧拉筛和埃氏筛哪个是寻找质数最快的方法

[复制链接]
发表于 2021-7-9 11:32:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本文涉及基础知识不多, 主要是算法层面, 没有使用第三方库

欧拉筛和埃氏筛是两种不同的寻找质数的方法, 欧拉筛相对更难理解, 但, 欧拉筛真的是最快的质数寻找方式吗?

不是

埃氏筛代码如下:
  1. def eratosthenes_sieve(n):
  2.     primes = []
  3.     flags = [True] * (n + 1)
  4.     flags[0], flags[1] = False, False
  5.     nums = range(n + 1)

  6.     for i in range(2, int(n ** 0.5) + 1):
  7.         if flags[i] == True:
  8.             for j in range(2 * i, n + 1, i):
  9.                 flags[j] = False

  10.     for i in range(n + 1):
  11.         if flags[i]:
  12.             primes += [nums[i]]
  13.             
  14.     return primes
复制代码

欧拉筛代码如下 (原代码):
  1. def euler_sieve(upper_bound):
  2.     filter_ = [False for i in range(upper_bound + 1)]
  3.     primeNumbers = []
  4.     for num in range(2, upper_bound + 1):
  5.         if not filter_[num]:
  6.             primeNumbers.append(num)
  7.             
  8.         for prime in primeNumbers:
  9.             if num * prime > upper_bound:
  10.                 break
  11.             
  12.             filter_[num * prime] = True
  13.             if num % prime == 0:
  14.                 break
  15.             
  16.     return primeNumbers
复制代码


测量时间代码如下:
  1. import time

  2. num = 1000000

  3. s1 = time.time()
  4. euler = euler_sieve(num)
  5. e1 = time.time()
  6. delta1 = e1 - s1

  7. s2 = time.time()
  8. eratosthenes = eratosthenes_sieve(num)
  9. e2 = time.time()
  10. delta2 = e2 - s2

  11. print(f'量级: {num}')
  12. print(f'欧拉筛用时: {delta1}')
  13. print(f'埃氏筛用时: {delta2}')
  14. print(f'时间差: {delta1 - delta2}')
  15. print(f'时间比: {delta1 / delta2}')
复制代码


输出如下:
  • 电脑1(速度较快) + 百万量级
    1. 量级: 1000000
    2. 欧拉筛用时: 0.21872687339782715
    3. 埃氏筛用时: 0.09372806549072266
    4. 时间差: 0.12499880790710449   
    5. 时间比: 2.3336326451704807
    复制代码

  • 电脑2(速度较慢) + 百万量级
    1. 量级: 1000000
    2. 欧拉筛用时: 0.635487586537008648
    3. 埃氏筛用时: 0.205665456564456546
    4. 时间差: 0.205665456564456546
    5. 时间比: 3.0899092008571882
    复制代码

  • 电脑1 + 千万量级 (电脑2的千万量级没做)
    1. 量级: 10000000
    2. 欧拉筛用时: 2.2177467346191406
    3. 埃氏筛用时: 1.596726894378662
    4. 时间差: 0.6210198402404785   
    5. 时间比: 1.3889330369688158
    复制代码

  • 电脑1 + 亿量级
    1. 量级: 100000000
    2. 欧拉筛用时: 22.43600082397461
    3. 埃氏筛用时: 17.96090292930603
    4. 时间差: 4.475097894668579   
    5. 时间比: 1.2491577351251508  
    复制代码

  • 电脑2 + 亿量级
    1. 量级: 100000000
    2. 欧拉筛用时: 64.61267971992493
    3. 埃氏筛用时: 26.365909576416016
    4. 时间差: 38.24677014350891
    5. 时间比: 2.450614477481186
    复制代码


    所以, 原因是什么?
    我的推断:
    1. 质数的分布: 质数的分布是非常不均匀的, 所以在数据量不足的情况下无法凸显出那个更快
    2. 循环次数: 按照循环次数推断, 欧拉筛的时间复杂度是O(n^2), 埃氏筛是O(n^3/2)



    仅代表个人观点, 没试过c++, 数据量也不够, 如果有人运行得出不同结果, 欢迎发在下方
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-10 15:52:20 | 显示全部楼层
沉的真快......
标题有那么吓人吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-10 15:59:36 | 显示全部楼层
不错
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-7-10 16:04:47 | 显示全部楼层
算法这种除非是系统的学习,一般人学习Python不会考虑这些的,虽然说计算时间会大于O^2,但是还行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-10 16:09:03 | 显示全部楼层
fish_nian 发表于 2021-7-10 16:04
算法这种除非是系统的学习,一般人学习Python不会考虑这些的,虽然说计算时间会大于O^2,但是还行

除了专门打OI类比赛的, 基本没人在意这个...
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-9-6 18:20:00 | 显示全部楼层
本帖最后由 傻眼貓咪 于 2021-9-6 18:21 编辑

我的代碼是採用試除法,小費馬定理和米勒-拉賓質數判定法寫的:
  1. def isPrime(n, k = 5):
  2.     from random import randint
  3.     if n < 2: return False
  4.     for p in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]:
  5.         if n % p == 0: return n == p
  6.     s, d = 0, n-1
  7.     while d % 2 == 0:
  8.         s, d = s+1, d/2
  9.     for i in range(k):
  10.         x = pow(randint(2, n-1), d, n)
  11.         if x == 1 or x == n-1: continue
  12.         for r in range(1, s):
  13.             x = (x * x) % n
  14.             if x == 1: return False
  15.             if x == n-1: break
  16.         else: return False
  17.     return True

  18. print(isPrime(100524249167)) # 極大數沒有問題
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-19 00:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表