021埃拉托色尼筛法 - 古希腊人的质数过滤器

埃拉托色尼筛法 - 古希腊人的质数过滤器

埃拉托色尼筛法:2200年的质数过滤器

5W1H 发明者故事

Who(何人)- 发明者是谁?

发明者:Eratosthenes of Cyrene(埃拉托色尼,约公元前 276-194 年)
背景

  • 古希腊博学者,生于北非昔兰尼(今利比亚)
  • 曾任亚历山大图书馆馆长
  • 数学家、天文学家、地理学家、诗人,是历史上最早测量地球周长的人(误差仅约 2-3%)
  • 亚里士多德的学生,柏拉图学派传人

现代分析贡献者

  • Donald E. Knuth 在 TAOCP 第二卷 4.5.4节详细分析了筛法的时间复杂度 O(N log log N)
  • Legendre 于 1808 年给出了筛法时间复杂度的早期分析

当时的处境:古希腊数学家对质数(素数)充满兴趣,欧几里得已在《几何原本》中证明了质数有无穷多个。埃拉托色尼需要一种系统方法来列举所有质数。

When(何时)- 什么时候发明的?

时间:约公元前 240 年
时代背景

  • 希腊化时代(Hellenistic Period),亚历山大大帝的帝国刚刚分裂
  • 亚历山大图书馆是当时世界上最大的知识中心,收藏了数十万卷手稿
  • 数学以几何为主流,算术和数论尚在发展中
  • 没有代数符号体系,所有数学用文字和几何图形表达
  • 算法的概念还不存在,但埃拉托色尼的方法已经具备了现代算法的特征:清晰的步骤、有限的操作、确定的终止

Where(何地)- 在哪里发明的?

地点:埃及亚历山大城(Alexandria),亚历山大图书馆
环境

  • 亚历山大图书馆是公元前 3 世纪的"知识工厂",雇佣了众多学者从事研究和抄录
  • 地中海沿岸,希腊、埃及、巴比伦三种文明的知识在此汇聚
  • 无纸时代,数学推导写在莎草纸(papyrus)上
  • 埃拉托色尼在此工作了约 50 年,晚年因眼盲而绝食身亡

What(何事)- 发明了什么?

算法:埃拉托色尼筛法(Sieve of Eratosthenes)
核心概念:从 2 开始,将所有 2 的倍数标记为"非质数",然后找下一个未标记的数(必为质数),将其所有倍数标记为"非质数",重复直到 √N。最终未被标记的数就是质数。就像用筛子(sieve)过滤,每次筛掉一种合数的倍数,留下的是质数。
关键突破

  • 主动标记合数,而非逐个测试每个数是否为质数
  • 每个合数只被其最小质因子"筛掉"(实际上现代优化版本中)
  • 时间复杂度 O(N log log N),空间 O(N)
  • 外层循环只需到 √N(因为大于 √N 的合数必有小于 √N 的质因子)

Why(何因)- 为什么发明?

要解决的问题

  1. 系统列举质数:古希腊数学家需要知道到某个数为止有哪些质数
  2. 验证数论猜想:研究质数分布规律需要大量具体的质数数据
  3. 计算需要:古代天文学计算需要分解大数,而分解需要质数表

当时的挑战

  • 没有算法概念,只有几何证明方法
  • 大数的计算极其费时(用算盘或手工计算)
  • 没有负数和零的概念,需要绕过这些限制
  • 如何证明算法的正确性和终止性

动机:在编纂数学知识的过程中,埃拉托色尼需要一个系统的方法来列举质数,供数论研究使用。他用一张数字表格,逐步划掉合数,就像用筛子过滤一样。

How(何果)- 如何实现?有什么影响?

算法步骤(现代描述)

1. 创建布尔数组 is_prime[0..N],初始全为 true
2. is_prime[0] = is_prime[1] = false(0和1不是质数)
3. for p = 2 to √N:
     若 is_prime[p] 为 true(p是质数):
       for j = p² to N, step p:
         is_prime[j] = false(标记 p 的倍数为合数)
         注意:从 p² 开始(小于 p² 的 p 的倍数已被更小的质数筛掉)
4. 所有 is_prime[i]=true 的 i 就是质数

历史影响

  • 保持了 2200 年的"最佳算法"地位(在朴素方法中),这在算法史上极为罕见
  • 现代变体(分段筛、线性筛)仍以此为基础
  • 密码学(RSA质数生成)和数论研究的基础工具
  • 编程竞赛中的标准算法,几乎每个程序员都实现过
  • 教学中用于说明算法效率和"筛法思想"(如 Eratosthenes → 线性筛 → 轮筛)

实际性能

N=10^6:找到 78498 个质数,约 10^6 次操作
N=10^8:找到 5761455 个质数,约 3×10^8 次操作(log log N ≈ 3)

名言:Knuth 在 TAOCP 中写道:“埃拉托色尼筛法是历史上最古老的算法之一,也是最优雅的算法之一。它的基本思想在 2000 年后仍未被超越。”


自然语言需求定义

需求名称:实现埃拉托色尼筛法,生成 N 以内所有质数

功能需求(用精确的中文描述)

  1. 创建筛(sieve):分配并初始化布尔数组

    • 输入:上界 N
    • 操作:calloc 分配 N+1 个字节,初始值全为1(true)
    • 输出:bool 数组指针
  2. 执行筛法:标记所有合数

    • 输入:bool 数组、上界 N
    • 操作:从 p=2 到 √N,若 is_prime[p] 为真,从 p² 开始标记 p 的倍数为假
    • 输出:无(原地修改数组)
  3. 收集质数:将所有未标记的数收集到结果数组

    • 输入:bool 数组、上界 N、结果数组指针、结果数量指针
    • 操作:遍历数组,收集所有 is_prime[i]=true 的 i
    • 输出:质数数组和数量
  4. 释放内存:释放筛数组

    • 输入:bool 数组
    • 输出:无

约束条件

  • N 可以达到 10^7(需要约 10MB 内存)
  • 从 p² 开始标记(优化:跳过已被标记的小倍数)
  • 外层循环只到 √N
  • 正确处理 N < 2 的边界情形(没有质数)

验收标准(必须可验证)

编号测试场景(自然语言描述)预期结果验证方式
1N=30 时,前10个质数[2,3,5,7,11,13,17,19,23,29]逐一比较
2N=100 时,质数数量25 个计数验证
3N=1000 时,质数数量168 个计数验证
4N=10000 时,第100个质数541索引验证
5质数的正确性(无遗漏、无误判)所有结果确实是质数用试除法验证前20个
6N=1(边界)0个质数计数为0

AI 生成提示

基于以上需求和验收标准,用标准C语言实现埃拉托色尼筛法。

要求:
1. 使用标准C99
2. 使用char数组(0/1)作为筛,比bool数组更节省内存
3. sieve_create(N) → char* / sieve_run(sieve, N) / sieve_get_primes(sieve, N, &count)
4. 外层循环到 sqrt(N),内层从 p*p 开始
5. 在main中实现全部6个验收标准
6. 测试通过输出 "✓ 测试X通过",失败输出 "✗ 测试X失败"

核心函数:
- sieve_of_eratosthenes(N, &count) → int*(返回质数数组,调用者free)
- is_prime_trial(n) → bool(试除法,用于验证)

C语言实现文件

对应文件: sieve_of_eratosthenes.c

编译运行:

gcc -std=c99 -Wall -o sieve_test sieve_of_eratosthenes.c -lm
./sieve_test

核心函数:

  • sieve_of_eratosthenes(N, count) - 返回 N 以内所有质数的数组
  • is_prime_trial(n) - 试除法(验证用)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值