求修复:埃拉托斯特尼筛法求100以内素数程序异常问题
问题分析与修复
你的代码存在两个核心问题导致j无法超过2:
1. 外层循环终止条件错误
原代码外层循环使用j <= num[99]作为终止条件,但num[99]初始值是100,当j=2执行内层循环时,n=50会计算出j*n=100,此时num[99]会被设为0。后续j自增到3时,3 <= 0不成立,循环直接终止,导致j永远无法处理3及以上的数。
2. 内层循环逻辑冗余且存在潜在风险
原代码内层循环用n从j开始遍历,计算j*n标记非素数,但j*j之前的倍数已经被更小的素数标记过(比如j=3时,6已经被j=2标记),重复标记会浪费性能;同时如果j过大,j*n可能超过100,导致数组越界(虽然100以内不会触发,但逻辑不严谨)。
修复后的代码
#include <stdio.h> int main() { int i, j, num[100], sum = 0; // 初始化数组:num[i] = i+1,对应1到100的数 for (i = 0; i < 100; i++) num[i] = i + 1; // 外层循环:遍历2到10,更高效的终止条件是j*j <=100(sqrt(100)=10) for (j = 2; j * j <= 100; j++) { // 如果当前j已经被标记为非素数,跳过无效处理 if (num[j-1] == 0) continue; // 内层循环:从j的平方开始标记倍数,避免重复处理已标记的数 for (int k = j * j; k <= 100; k += j) { num[k-1] = 0; } } // 求和:累加2到100中未被标记的素数(跳过了num[0]的1) for (i = 1; i < 100; i++) { if (num[i] != 0) sum += num[i]; } printf("%d\n", sum); return 0; }
额外说明
- 终止条件改为
j*j <=100:大于sqrt(100)的数如果没被标记,必然是素数,无需再处理其倍数,大幅提升效率。 - 内层循环从
j*j开始:避免重复标记已被更小素数处理过的倍数,减少冗余操作。 - 增加
if(num[j-1]==0) continue:跳过已被标记为非素数的j,避免无效遍历。
内容的提问来源于stack exchange,提问作者Vinayak Deshmukh
相关产品推荐
相关产品推荐

