如何判断一个数是否是质数?

来源:前端技术作者:俊华头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何判断一个数是否是质数?》,敬请观看详情。写业务代码时经常要确认某个整数能不能被拆成两个大于一的整数乘积。质数的本质是除了1和自身外没有其他正因数,判断时若从2一直试除到n减一显然太慢。更合理的做法是只检查到平方根,因为若n等于a乘b且a小于等于b,那么a必然不超过根号n。对于大数还有概率性的米勒拉宾测试,用少量随机底数就能以极高把握判定。本文整理从最基础的遍历试除到高效算法的实现细节,并给出不同规模数据下的选用建议,帮你少走弯路。

质数又称素数,指的是大于1且只能被1和自身整除的整数。判断一个数是否为质数,是数论与日常编程中最基础的问题之一。根据数的范围不同,我们可以选择从简单试除到概率算法的多种方案。

如何判断一个数是否是质数?

最基础的试除法

最直观的思路是从2开始,依次用每个小于n的整数去除n,如果其中存在某个数能整除n,那么n就不是质数。这种方法逻辑简单,适合刚接触算法的初学者理解质数的数学定义。

不过这种写法效率很低。假设我们要判断n是否为质数,最坏情况下需要循环n减2次。当n很大时,这种线性增长的时间复杂度完全不可接受。下面的代码展示了最原始的写法:

def is_prime_basic(n):
    if n <= 1:
        return False
    for i in range(2, n):
        if n % i == 0:
            return False
    return True

# 测试
print(is_prime_basic(17))  # True
print(is_prime_basic(15))  # False

上述代码在n为100万时,需要执行接近百万次取模运算,显然不适合处理稍大的数值。但它的价值在于清晰地表达了质数“无其他因素”的定义。

优化到平方根的试除

数学上有一个重要性质:如果n可以分解为a乘b,且a小于等于b,那么a最大不会超过根号n。这意味着我们只需检查2到根号n之间的整数,就能覆盖所有可能的因数组合。

将循环上限改为整数平方根后,时间复杂度从O(n)降为O(根号n),性能提升非常明显。对于绝大多数工程场景下的中等大小整数,这种写法已经足够快,而且结果是绝对准确的。

import math

def is_prime_sqrt(n):
    if n <= 1:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    limit = int(math.sqrt(n)) + 1
    for i in range(3, limit, 2):
        if n % i == 0:
            return False
    return True

# 测试
print(is_prime_sqrt(97))   # True
print(is_prime_sqrt(100))  # False

代码中还顺手排除了偶数,进一步将循环次数减半。这种小优化在批量判断时积累起来的收益很可观。

跳过更多倍数的进阶试除

除了排除偶数,我们还可以利用“质数大于3时都满足6k加减1”的规律。任何整数都可以写成6k、6k加1、6k加2、6k加3、6k加4、6k加5,其中能被2或3整除的形式都不是质数(除2和3本身)。

因此判断时只需测试6k减1和6k加1形式的数,能把候选除数再缩减约三分之一。虽然复杂度阶数没变,但常数因子更小,实际运行更快。

import math

def is_prime_6k(n):
    if n <= 1:
        return False
    if n <= 3:
        return True
    if n % 2 == 0 or n % 3 == 0:
        return False
    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i += 6
    return True

# 测试
print(is_prime_6k(101))  # True
print(is_prime_6k(91))   # False,7乘13

这种写法在单线程Python里判断千万级别以内的数都很轻松,是手写工具函数时的常用选择。

大数场景下的米勒拉宾测试

当数字达到几十位甚至上百位的加密场景时,试除法彻底失效。此时通常采用米勒拉宾这种概率性素数测试:它基于费马小定理的变体,通过随机选取底数进行幂模运算,能在极短时间内以极高概率给出正确结论。

米勒拉宾测试本身可能把极少数“强伪素数”误判为质数,但多轮不同底数测试后错误率可降到忽略不计。下面是Python中使用标准库实现的示例:

import random

def is_prime_miller_rabin(n, k=5):
    if n < 2:
        return False
    # 小数字直接试除
    for p in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]:
        if n % p == 0:
            return n == p
    # 写出 n-1 = d * 2^s
    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1
    for _ in range(k):
        a = random.randrange(2, n - 1)
        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(s - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
    return True

# 测试
print(is_prime_miller_rabin(999983))  # True

该算法时间复杂度为O(k乘log三次方n),适合密码学、随机大质数生成等任务。如果业务要求绝对确定性,可结合确定性的米勒拉宾底数集合使用。

不同方案的选用建议

对于日常接口开发或面试题里常见的三十二位以内整数,平方根试除或6k优化法已经完全够用,代码易读且零依赖。若你处理的是批量小数据,还可以预先筛出质数表再用查表法加速。

一旦涉及安全通信、密钥生成等超大整数,请直接使用语言标准库或成熟加密库中的概率测试,不要自己造轮子试除。下表简要对比了几种方法:

方法时间复杂度准确性适用场景
基础试除O(n)确定教学演示
平方根试除O(根号n)确定普通业务数值
6k优化试除O(根号n)确定手写高效工具
米勒拉宾O(k乘log三次方n)概率极高大数密码学

理解这些方法的底层差异,你就能在写代码时针对数据规模做出合理的取舍,而不是盲目套用某一种写法。

质数判断素数算法时间复杂度修改时间:2026-08-01 03:39:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。