使用 c 语言找出 100 以内所有的素数,核心思路就是逐个判断 2 到 100 之间每一个数字是不是素数,素数也叫质数,定义是大于 1 的自然数,除了 1 和它本身之外,不能被其他任何整数整除,2 是最小的素数,1 不属于素数,这一点写代码的时候很容易搞错。基础实现一般采用双层循环,外层循环遍历待检测数字,内层循环做试除判断,还可以优化算法,把试除上限缩小到数字的平方根,减少循环次数,也可以使用埃氏筛法,效率比试除法更高,适合批量找出一定范围内素数。c 语言找出 100 以内所有的素数这个题目是入门经典练习题,主要考察循环嵌套 判断语句 标记变量的使用,同时帮助理解素数数学定义,很多初学者出错是把 1 当成素数,或者内层循环边界写错,导致部分素数漏判或者误判。
素数基础定义
素数必须同时满足两个条件
第一 数值大于 1
第二 从 2 开始到这个数字减 1 之间,没有任何整数可以整除它
举例子 7,用 2 到 6 去试除,全部都不能整除,所以 7 是素数
举例子 9,可以被 3 整除,所以 9 不是素数
方法一 基础试除法
实现思路
外层循环变量 n,取值从 2 一直到 100
设置标记变量 isPrime,初始值设置为 1,代表默认这个数字是素数
内层循环 i 从 2 开始,循环到 n 减 1,如果 n 对 i 取模等于 0,说明可以整除,标记改成 0,直接跳出内层循环
内层循环结束之后,如果标记仍然是 1,就输出这个 n
核心代码逻辑说明
标记变量是这个写法的关键,默认假定数字是素数,一旦发现可以整除,就修改标记,后面不再继续试除,减少无效循环。
这个方法优点是代码简单易懂,适合初学 c 语言找出 100 以内所有的素数,缺点是循环次数偏多,数字变大之后运算效率偏低。
方法二 优化试除法
优化原理
如果一个数字 n 存在大于平方根的因数,那么对应的另一个因数一定小于平方根,所以内层循环只需要循环到根号 n 就足够,不需要一直试除到 n 减 1。
实现要点
内层循环终止条件改为 i 小于等于 sqrt (n),需要引入 math 头文件的 sqrt 函数,也可以不用 sqrt,写成 i 乘以 i 小于等于 n,避免引入头文件。
这个优化之后,c 语言找出 100 以内所有的素数,内层循环次数明显减少,100 这个范围差距不算特别大,但是数字范围扩大之后,优化效果会非常明显。
方法三 埃氏筛法
算法原理
先建立一个数组,把 2 到 100 全部标记为是素数,然后从最小素数 2 开始,把 2 所有倍数全部标记成非素数,接着找到下一个还没有被标记的数字,也就是 3,再把 3 所有倍数标记成非素数,重复这个操作,一直处理到根号 100,最后数组里面仍然标记为素数的数字,就是全部结果。
特点
埃氏筛法是批量筛选素数经典算法,相比逐个试除,不需要对每个数字单独做多层试除,适合大范围找素数,在 c 语言找出 100 以内所有的素数题目里面,这个写法可以拓展算法思维,考试或者作业如果要求进阶实现,优先考虑这个方案。
三种方法对比表
| 算法名称 | 核心原理 | 优点 | 缺点 |
|---|---|---|---|
| 基础试除法 | 逐个数字试除到 n 减 1 | 代码最简单,容易理解 | 循环次数多,效率低 |
| 优化试除法 | 试除上限缩小到平方根 | 计算量下降,改动小 | 仍然是逐个数字单独判断 |
| 埃氏筛法 | 批量标记倍数筛除非素数 | 批量处理,大范围效率高 | 需要数组,理解难度更高 |
深度易错点解析
第一点 1 不是素数,外层循环一定要从 2 开始,如果从 1 开始遍历,程序会错误把 1 输出成素数。
第二点 偶数里面只有 2 是素数,其他大于 2 的偶数全部可以被 2 整除,代码优化的时候可以直接跳过偶数,进一步减少循环。
第三点 取模运算,判断整除使用 n% i 等于 0,不要写成除法判断,除法会丢失余数信息。
第四点 使用 sqrt 函数的时候,返回值是浮点数,循环比较的时候注意类型转换,浮点数精度有可能带来边界错误,所以很多教材推荐 ii<=n 这种写法。
第五点 标记变量重置,每一轮外层循环开始之前,都要重新把标记置为 1,如果忘记重置,上一轮的标记会残留,造成判断错误,这是双层循环最常见 bug。
【常见问题】
问题 1 c 语言找出 100 以内所有的素数,为什么不能把 1 判定成素数
回答 1 按照素数数学定义,c 语言找出 100 以内所有的素数的时候,素数要求大于 1,1 只有一个因数,不满足素数定义,所以代码外层循环必须从 2 开始,不能把 1 纳入素数输出结果。
问题 2 c 语言找出 100 以内所有的素数,试除法为什么可以优化到平方根
回答 2 c 语言找出 100 以内所有的素数,试除法优化到平方根是因为因数成对出现,如果 n 有大于平方根的因子,一定配套存在小于平方根的因子,只要小于平方根范围内没有因数,就可以确定它是素数,不需要继续试除。
问题 3 c 语言找出 100 以内所有的素数,埃氏筛法相比试除法优势是什么
回答 3 c 语言找出 100 以内所有的素数,埃氏筛法是批量标记倍数,不需要对每一个数字单独多层试除,当筛选范围变大的时候,埃氏筛法运算速度明显优于普通试除法,适合大批量素数筛选场景。
问题 4 c 语言找出 100 以内所有的素数,标记变量忘记重置会出现什么错误
回答 4 c 语言找出 100 以内所有的素数,如果每轮外层循环没有重置标记变量,上一轮非素数的标记会保留,后续数字即使本身是素数,也会被错误判定成非素数,出现素数漏输出的 bug。
【免责申明】
本文是 c 语言找出 100 以内所有的素数相关算法解析,代码思路基于标准 c 语言语法,不同编译器对于 math 头文件函数支持细节略有差异,示例算法仅用于学习练习,实际更大范围素数计算还需要额外考虑数据类型溢出问题,本文不保证所有拓展场景完全适配。


