Python – 获取 100 以内的质数(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

质数(Prime Number)是数学中一个基础但重要的概念,它指的是只能被 1自身 整除的大于 1 的自然数。例如,2、3、5、7 等都是质数,而 4、6、8、9 等则不是。在编程领域,尤其是 Python 中,如何高效获取一定范围内的质数,是初学者和中级开发者常遇到的实践问题。本文将从基础概念出发,逐步讲解多种实现方法,并通过 代码示例性能对比,帮助读者掌握“Python – 获取 100 以内的质数”的核心技巧。


一、质数的基本概念与判断逻辑

1.1 质数的数学定义

质数的定义可以用一句话概括:

一个大于 1 的自然数,如果除了 1 和它本身之外,没有其他因数,则称为质数。

例如,5 是质数,因为它只能被 15 整除;而 6 不是质数,因为它还能被 23 整除。

1.2 判断质数的核心逻辑

判断一个数是否为质数,可以通过以下步骤实现:

  1. 排除小于 2 的数:直接判定为非质数。
  2. 尝试除以 2 到该数的平方根之间的所有整数:如果存在能整除的数,则不是质数;否则是质数。

为什么只需要检查到平方根?
这里可以用一个比喻:

想象你有一块长方形的巧克力,面积是 N。如果一边的长度超过√N,另一边就必须小于√N。因此,若 N 有因数大于√N,必然存在一个对应的因数小于√N。因此,检查到√N 就足够了。


二、Python 实现质数判断的代码基础

2.1 简单暴力法(Brute Force)

最基础的实现方式是遍历所有可能的因数:

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

缺点分析

  • n 较大时(如 100),循环次数过多。例如判断 100 是否为质数时,需要循环 98 次。
  • 效率低,不适合处理更大的数据范围。

2.2 优化到平方根的循环

通过计算 平方根 作为循环的上限,可以大幅减少循环次数:

import math

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

改进效果

  • n = 100 为例,原暴力法需要循环 98 次,而优化后仅需循环 10 次(sqrt(100) = 10)。

三、生成 100 以内质数的多种方法

3.1 方法一:遍历 + 单个判断函数

通过循环 2 到 100 的所有数,并调用上述优化后的 is_prime_optimized 函数:

primes = []
for num in range(2, 101):
    if is_prime_optimized(num):
        primes.append(num)
print(primes)

输出结果

[2, 3, 5, 7, 11, ..., 89, 97]

3.2 方法二:列表推导式(List Comprehension)

用更简洁的 Python 语法实现相同逻辑:

primes = [num for num in range(2, 101) if is_prime_optimized(num)]
print(primes)

四、进阶优化:埃拉托斯特尼筛法(Sieve of Eratosthenes)

4.1 筛法的数学原理

筛法 是一种古老的质数筛选算法,其核心思想是:

  1. 初始化一个布尔型数组 is_prime,初始值全设为 True
  2. 2 开始,将当前数的所有倍数标记为 False
  3. 重复步骤 2,直到处理到平方根位置。

形象比喻

想象你有一张写满数字的网格纸,每次划掉当前质数的所有倍数,剩下的未被划掉的数字就是质数。

4.2 Python 实现代码

def sieve_of_eratosthenes(limit):
    is_prime = [True] * (limit + 1)
    is_prime[0], is_prime[1] = False, False  # 0和1不是质数
    
    for num in range(2, int(limit**0.5) + 1):
        if is_prime[num]:
            # 标记num的倍数为非质数
            for multiple in range(num*num, limit+1, num):
                is_prime[multiple] = False
    
    primes = [num for num, prime in enumerate(is_prime) if prime]
    return primes

print(sieve_of_eratosthenes(100))

性能对比
| 方法 | 时间复杂度 | 适用场景 | |--------------------|------------|------------------------| | 暴力法 | O(n²) | 小规模数据(如 n ≤ 100)| | 平方根优化法 | O(n√n) | 中等规模数据 | | 埃拉托斯特尼筛法 | O(n log log n) | 大规模数据(如 n = 1e6) |


五、代码封装与函数复用

5.1 封装质数生成函数

将上述方法封装为一个可复用的函数,支持动态调整范围:

def get_primes_up_to(limit=100, method='sieve'):
    if method == 'sieve':
        return sieve_of_eratosthenes(limit)
    else:
        primes = []
        for num in range(2, limit+1):
            if is_prime_optimized(num):
                primes.append(num)
        return primes

print(get_primes_up_to(100, method='sieve'))

5.2 单元测试验证

编写简单测试用例,确保函数正确性:

def test_primes():
    assert get_primes_up_to(10) == [2, 3, 5, 7]
    assert get_primes_up_to(2) == [2]
    assert get_primes_up_to(1) == []
    print("所有测试通过!")

test_primes()

六、常见问题与扩展思考

6.1 为什么从 2 开始遍历?

因为 1 不是质数,且所有自然数都可以被 1 整除,因此遍历从 2 开始。

6.2 如何处理更大的范围(如 1000 或 10000)?

  • 筛法 是更优的选择,其时间复杂度远低于逐个判断的方法。
  • 可以进一步优化筛法的内存使用,例如使用位操作或布尔数组的压缩形式。

6.3 是否有其他数学库或工具可用?

Python 的 sympy 库提供了现成的质数函数:

from sympy import primerange
print(list(primerange(1, 100)))

结论

通过本文的讲解,读者可以掌握以下关键内容:

  1. 质数的数学定义与判断逻辑。
  2. 从暴力法到筛法的算法优化路径。
  3. Python 中的代码实现与性能对比。

“Python – 获取 100 以内的质数” 不仅是一个基础编程问题,更是理解算法优化与数学思维结合的典型案例。无论是编程初学者通过基础循环理解逻辑,还是中级开发者通过筛法提升效率,本文提供的方法与思路都具有实际参考价值。

希望读者能够将这些知识应用到更复杂的场景中,例如密码学、数据加密或数学建模等领域,进一步探索 Python 在算法实现中的强大能力。

最新发布