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

相关推荐
小雉系统7 小时前
BcoreOS安全通信架构:FsSession 抗算法后门安全设计
算法·安全·架构
金銀銅鐵8 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
§ꦿCFོ༉8 小时前
嵌入式八股文—C语言入门学习(四)
c语言·开发语言·学习
吴名氏.9 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
.痞老板.10 小时前
java ee--多线程(进阶)
java·java-ee
深入云栈12 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
唐墨12312 小时前
linux kernel 比较数据大小的宏定义
linux·算法
拂拉氏12 小时前
【知识讲解-题目讲解】 统计满足K约束的子字符串数量2 (滑动窗口+前缀和+二分查找+分析)
算法·前缀和·二分查找·滑动窗口
wang_shu_mo_ran13 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis