只需筛到√n,因合数必有≤√n的质因子;外层循环上限设为(int)math.sqrt(n)+1防浮点误差,或用i*i

Java 中实现素数筛法(如埃拉托斯特尼筛法)时,循环结构是核心,优化关键在于减少冗余计算、合理设置边界和避免重复标记。下面从常用优化点出发,给出清晰实用的写法。
只筛到 √n,大幅减少外层循环次数
合数 n 必定有一个 ≤ √n 的质因子,因此只需用 ≤ √n 的质数去筛即可。超出部分无需再作为“筛子”参与外层循环。
- 外层 for 循环上限设为 (int) Math.sqrt(n) + 1,注意加 1 防止因浮点误差漏掉边界
- 若用 while 循环,条件可写为 i * i ,更简洁且无类型转换风险
- 例如筛 100 以内素数,外层只需运行到 i = 10,而非 100
内层从 i² 开始标记,跳过已被更小质数筛过的数
小于 i² 的合数(如 2i、3i…(i−1)i)一定已被更小的质数(2、3…i−1)标记过,重复标记浪费时间。
- 内层循环起始值设为 i * i,而非 2 * i
- 需确保 i * i 不越界:循环条件加 j 或 j
- 例如 i = 5 时,直接从 25 开始标记,跳过 10、15、20(它们已被 2 或 3 标记)
跳过偶数,用布尔数组+步长优化空间与时间
除 2 外,所有偶数都不是素数。可单独处理 2,其余只考虑奇数,将数组大小减半,循环步长翻倍。
- 声明布尔数组时长度为 n / 2 + 1,索引 k 对应数字 2*k + 1
- 外层循环从 i = 3 开始,步长为 2(只遍历奇数)
- 内层标记也按奇数步长推进,例如对奇数 i,其奇倍数从 i² 开始,每次加 2*i
- 这样既省空间,又让内层循环次数减半
使用位运算或 BitSet 进一步压缩内存(适用于大 n)
当 n 较大(如 10⁷ 以上)时,boolean[] 每个元素占 1 字节,浪费明显。BitSet 用 long 数组存储,每个 bit 表示一个数,空间降为约 1/8。
- 初始化 BitSet bs = new BitSet(n + 1)
- 标记合数用 bs.set(compositeIndex),判断是否为素数用 !bs.get(index)
- 注意 BitSet 默认所有位为 false,需先将 0 和 1 设为 true(即标记为非素数)
- 配合前述 √n 和 i² 起始优化,性能提升显著
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











