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 语言的基础练习,更是理解算法复杂度优化的重要一步。建议初学者先掌握基础写法,再逐步理解优化思路,最后尝试用筛法解决更大规模的问题。

相关推荐
谢亮_vipxieliang2 小时前
Spring Boot 自动配置原理:从 @SpringBootApplication 到自定义 Starter
java·spring boot·后端
v:PLLucky202 小时前
农作物病虫害检测识别系统
深度学习·scrapy·算法·百度·微信公众平台
朝朝辞暮i2 小时前
C++ 第一阶段总结:从零基础到 ROS2 前置语法
开发语言·c++·算法
朝朝辞暮i2 小时前
C++ 第 25 课:getter / setter + this
java·javascript·c++
蜗牛互联网2 小时前
Python接入Gemini 3.8 Flash实现票据视觉抽取与规则校验
java·javascript·网络·人工智能·python
H.莓飛2 小时前
【数据结构】链表_OJ题
linux·数据结构·算法·链表
用户094248568032 小时前
第22章:JIT编译分层——Interpreter、C1、C2与热点探测
java·jvm
周杰偷奶茶2 小时前
【JavaSE】类和对象基础
java·开发语言
All for pursuit.2 小时前
【回溯-4】46.全排列
数据结构·c++·算法·leetcode