跳转到主要内容
杨月昌的软件博客
返回

Python 算法实战:从初级到骨灰级的素数判定函数

1. 素数判定的基本逻辑

素数(Prime Number)是指在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的数。

在编写函数时,新手最容易在边界条件(Corner Cases)上栽跟头。最常见的误区是:


2. 演进方案:从 到

方案 A:标准平方根法(基础款)

通过数学证明,如果一个数 不是素数,它必然有一个因子小于或等于 。

import math

def is_prime_v1(n):
    if n <= 1: return False
    # 循环范围 [2, sqrt(n)]
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

分析:虽然逻辑正确,但它对每一个数字(包括大量的偶数)都进行了取模运算。

方案 B:6k ± 1 高效法(进阶款)

这是目前单数判定中最高效的启发式算法之一。其核心数学原理是:除了 2 和 3,所有的素数都可以表示为 的形式。


3. 最终优化实现

以下是结合了边界处理与 6k 优化的完整代码:

import math

def is_prime(n):
    """
    高效判断一个数是否为素数
    """
    # 1. 处理小于等于 3 的特殊情况
    if n <= 3:
        return n > 1
    
    # 2. 排除能被 2 或 3 整除的数
    # 这一步可以瞬间过滤掉 2/3 的非素数数据
    if n % 2 == 0 or n % 3 == 0:
        return False
    
    # 3. 核心循环:步长为 6,只检查 6k ± 1
    # 初始 i = 5 (即 6*1 - 1),下一次循环 i = 11 (即 6*2 - 1)
    limit = int(math.sqrt(n)) + 1
    for i in range(5, limit, 6):
        # 检查 i (6k-1) 和 i+2 (6k+1)
        if n % i == 0 or n % (i + 2) == 0:
            return False
            
    return True

4. 优化点解析

  1. 空间换时间:通过显式处理 2 和 3 的倍数,我们在进入昂贵的 for 循环之前,就已经排除掉了约 66.6% 的合数。
  2. 步进优化:将 range 的步长设为 6。在每一次循环中,我们同时测试 和 。这意味着我们的迭代次数只有标准方法的 1/3
  3. 计算优化math.sqrt(n) 在循环外计算一次,避免在每次循环迭代时重复计算开方。

5. 总结与性能建议

算法版本时间复杂度1,000,000 次判定耗时 (参考)推荐场景
全量循环极慢仅限教学演示
平方根法较快通用情况
6k ± 1 法极快大数判定/工程实践

如果你的应用场景需要批量生成大量素数(例如 1 到 1000 万之间的所有素数),那么单次判定就不再合适,此时建议研究 埃拉托斯特尼筛法(Sieve of Eratosthenes)



上一篇
SQL Server 日期查询实战:从基础到高级优化技巧
下一篇
FluentScheduler:C# 中的任务调度神器