C语言素数判断:从入门到进阶

1. 什么是素数

素数(又称质数)是指大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的数。例如 2、3、5、7、11 都是素数,而 4、6、8、9 都不是素数。

判断一个数是否为素数,是 C 语言初学者最经典的练习题目之一,也是后续学习算法优化、数论的基础。

2. 最基础的判断方法

最直观的思路:对于一个数 n,从 2 开始一直试除到 n-1,如果中间存在某个数能整除 n,则 n 不是素数;否则 n 是素数。

c 复制代码
#include <stdio.h>

int isPrime(int n) {
    if (n <= 1) {
        return 0;  // 1 和负数不是素数
    }
    for (int i = 2; i < n; i++) {
        if (n % i == 0) {
            return 0;  // 能被整除,不是素数
        }
    }
    return 1;  // 是素数
}

int main() {
    int num;
    printf("请输入一个整数:");
    scanf("%d", &num);

    if (isPrime(num)) {
        printf("%d 是素数\n", num);
    } else {
        printf("%d 不是素数\n", num);
    }
    return 0;
}

这种方法虽然正确,但效率较低。当 n 很大时,循环次数接近 n 次,时间复杂度为 O(n)。

3. 优化一:只需判断到 √n

观察可以发现:如果 n 有一个大于 √n 的因数 a,那么必然存在一个小于 √n 的因数 b = n / a。因此,我们只需要从 2 试除到 √n 即可。

c 复制代码
#include <stdio.h>
#include <math.h>

int isPrime(int n) {
    if (n <= 1) {
        return 0;
    }
    for (int i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

这样时间复杂度降为 O(√n),性能大幅提升。

4. 优化二:跳过偶数

除了 2 以外,所有偶数都不是素数。因此可以先单独判断 2,然后从 3 开始只检查奇数。

c 复制代码
int isPrime(int n) {
    if (n <= 1) {
        return 0;
    }
    if (n == 2) {
        return 1;  // 2 是素数
    }
    if (n % 2 == 0) {
        return 0;  // 偶数不是素数
    }
    for (int i = 3; i <= sqrt(n); i += 2) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

这样循环次数又减少了一半,效率进一步提升。

5. 综合示例:输出 1~100 之间的所有素数

下面把上面的优化综合起来,输出 1 到 100 之间的所有素数:

c 复制代码
#include <stdio.h>
#include <math.h>

int isPrime(int n) {
    if (n <= 1) {
        return 0;
    }
    if (n == 2) {
        return 1;
    }
    if (n % 2 == 0) {
        return 0;
    }
    for (int i = 3; i <= sqrt(n); i += 2) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

int main() {
    printf("1~100 之间的素数有:\n");
    for (int i = 1; i <= 100; i++) {
        if (isPrime(i)) {
            printf("%d ", i);
        }
    }
    printf("\n");
    return 0;
}

运行结果:

复制代码
1~100 之间的素数有:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

6. 进阶:埃拉托斯特尼筛法

当需要一次性判断大量数字(比如求 1 到 1000000 之间所有素数)时,逐个判断效率太低。此时可以使用埃拉托斯特尼筛法(Sieve of Eratosthenes),时间复杂度为 O(n log log n)。

基本思想:从 2 开始,把每个素数的倍数都标记为合数,剩下的就是素数。

c 复制代码
#include <stdio.h>
#include <stdbool.h>

void sieve(int n) {
    bool isPrime[n + 1];
    for (int i = 0; i <= n; i++) {
        isPrime[i] = true;
    }
    isPrime[0] = isPrime[1] = false;

    for (int i = 2; i * i <= n; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j <= n; j += i) {
                isPrime[j] = false;
            }
        }
    }

    printf("1~%d 之间的素数有:\n", n);
    for (int i = 2; i <= n; i++) {
        if (isPrime[i]) {
            printf("%d ", i);
        }
    }
    printf("\n");
}

int main() {
    sieve(100);
    return 0;
}

7. 总结

方法 时间复杂度 适用场景
基础试除法 O(n) 小数字、教学演示
试除到 √n O(√n) 单个数字判断
跳过偶数优化 O(√n/2) 单个数字判断(推荐)
埃拉托斯特尼筛法 O(n log log n) 批量判断大量数字

掌握素数的判断方法,不仅能帮助你通过 C 语言的基础练习,更是理解算法复杂度优化的重要一步。建议初学者先掌握基础写法,再逐步理解优化思路,最后尝试用筛法解决更大规模的问题。

相关推荐
frjc14 小时前
Spring AI 里 ChatClient 和 ChatModel 有什么区别?什么时候该用哪个?
java·开发语言·spring·ai
Wang's Blog14 小时前
Java 项目实战: 交友项目 - 圈子功能的表设计方案
java·开发语言·交友
碧海银沙音频科技研究院14 小时前
基于炬芯ATS308X的DNN全连接神经网络手写数字识别系统设计
人工智能·深度学习·算法
文丑颜不良啊14 小时前
LeetCode601~625题目解析
java·leetcode
stolentime14 小时前
SOS DP学习笔记
c++·笔记·学习·算法·贪心算法·动态规划·二进制
文丑颜不良啊14 小时前
LeetCode651~675题目解析
java·leetcode
水母量化14 小时前
量化收益率计算别混用:算术均值、几何均值与对数收益
算法·均值算法·量化交易
frjc14 小时前
Spring WebFlux SSE 长连接,可以替换为 Java 21 虚拟线程吗?
java·人工智能·spring·ai·ai编程
xunberg15 小时前
【生命科学 Agent】推理平台(三)
算法·程序员·架构