怎么用Python写九九乘法表和素数判断?入门算法代码
在 Python 初学阶段,很多读者在掌握了基本变量赋值与单层判断后,面对的头两道经典算法关卡就是“九九乘法表”与“素数判断”。前者考察的是如何通过双重循环控制行与列的递进,并在终端输出对齐的文本;后者考察的是如何通过循环遍历与除法余数判断数值性质,并结合数学规律进行计算剪枝。本文直接提供这两个典型问题的标准代码实现,解析循环控制变量的绑定关系与平方根优化原理,帮助读者建立清晰可靠的代码实现直觉。
一、九九乘法表的实现:双重循环与输出格式化
九九乘法表本质上是一个标准的下三角矩阵输出问题。我们在纸上背诵的乘法口诀共有 9 行,第 1 行输出 1 列(1×1=1),第 2 行输出 2 列(1×2=2 到 2×2=4),以此类推,第 i 行输出 i 个乘法算式。因此,解决这一问题的核心逻辑就是使用外层循环遍历行号,内层循环遍历列号,并让列号的遍历上限绑定到当前行号。
1. 核心代码实现
在 Python 3 中,标准实现只需要四行代码:
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}x{i}={i * j}", end="\t")
print()
运行上述代码后,终端将输出结构规整的 9 行乘法算式,相邻列之间通过制表符 \t 保持平整对齐,每打印完一行后执行一次无参数的 print() 完成换行。
2. 核心语法细节与避坑说明
range()的左闭右开区间:Python 中range(1, 10)生成的数字是 1 到 9,不会包含 10。同理,若要在内层循环中取到i,第二个参数必须写为i + 1。初学者常误写成range(1, i),这会导致每一行都少算最后一项(例如第 2 行只会输出 1×2,漏掉 2×2)。end="\t"抑制换行:Python 的print()函数默认在末尾追加换行符\n。设置end="\t"可以让后续输出紧跟在当前算式后面,并通过制表符预留对齐间隙。- 外层缩进的换行
print():最后的print()必须与内层的for循环平级对齐。它的作用是在内层一整行所有算式输出完毕后,打印一个回车换行,供下一行使用。
二、素数判断算法:从试除法到平方根优化
素数(质数)是指在大於 1 的自然数中,除了 1 和它本身以外不再有其他因数的数。例如 2, 3, 5, 7, 11 是素数,而 4, 6, 8, 9, 10 属于合数。判断一个正整数 n 是否为素数,是理解算法复杂度与数学优化的绝佳案例。
1. 基础解法:暴力试除法
最直观的方法就是遵循定义:先特判小于等于 1 的数(既不是素数也不是合数),然后用 2 到 n - 1 之间的每一个整数去试除 n。只要找到任何一个能整除 n 的数,就说明 n 是合数;若全部遍历完都没有找到因子,则说明 n 是素数。
def is_prime_basic(n: int) -> bool:
if n <= 1:
return False
for i in range(2, n):
if n % i == 0:
return False # 找到因子,立即判定为非素数
return True # 遍历结束无因子,判定为素数
基础试除法逻辑简单,但存在明显的性能缺陷。当输入数字 n 较大(例如 n = 1000000007)时,循环需要执行约 10 亿次,造成不必要的 CPU 资源消耗。
2. 核心进阶:平方根数学优化 (O(√n))
若正整数 n 能被因数 d 整除,即 n = d * q,那么因数 d 和商 q 必定成对出现。如果 d 和 q 都大于 √n,则它们相乘 d * q > √n * √n = n,这与 d * q = n 产生矛盾。因此,如果一个数存在非自身的因数,那么其中至少有一个因数必然小于或等于 √n。
这意味着试除的范围不需要一直检查到 n - 1,只需要检查到 ⌊√n⌋ 即可。此外,除了 2 是偶素数以外,所有大于 2 的偶数必然不是素数。我们可以先排除偶数,然后只以步长 2 检查奇数因子。
import math
def is_prime(n: int) -> bool:
# 步骤 1:处理边界与小质数
if n <= 1:
return False
if n == 2:
return True
if n % 2 == 0:
return False # 排除所有大于 2 的偶数
# 步骤 2:仅检测奇数因数,上限裁剪到 int(math.isqrt(n))
limit = math.isqrt(n)
for i in range(3, limit + 1, 2):
if n % i == 0:
return False
return True
math.isqrt()?在 Python 3.8 及更高版本中,内置的 math.isqrt(n) 会直接返回整数平方根的下取整值,内部采用整数位移与牛顿法,既避免了浮点数 n ** 0.5 在超大整数时的精度截断误差,运算速度也更高效。
3. 素数判断的四个易错点
- 负数、0 和 1 的处理:这是最常见的逻辑漏洞。
0和1不是素数,负数同样不是素数,在执行任何循环前必须先做if n <= 1: return False拦截。 - 数字 2 的特判:
2是偶数,但它是素数中唯一的偶素数。若先过滤偶数n % 2 == 0,必须先确认n == 2返回True。 range右边界的+1:range(3, limit + 1, 2)中必须写limit + 1。如果传入n = 9,其平方根为 3,若写成range(3, 3)循环将直接不执行,从而导致把 9 误判为素数。- 开方后的步长推进:在排除了大于 2 的所有偶数后,接下来的因数只需检查奇数(3, 5, 7, 9...),因此
range的第三个参数设为2,可直接把循环计算量再减半。
三、算法逻辑与循环模式总结
九九乘法表与素数判断是 Python 控制流的代表性练习:九九乘法表展示了如何通过内外层循环变量的依存关系构建二维输出结构;素数判断展示了如何通过数学性质(因数对称性)压缩搜索空间。下表汇总了两个算法的关键技术点:
| 任务目标 | 核心控制结构 | 循环区间控制 | 核心优化 / 技巧 | 时间复杂度 |
|---|---|---|---|---|
| 九九乘法表 | 双重嵌套 for 循环 | range(1, 10) 与 range(1, i+1) |
end="\t" 水平对齐与外层 print() 换行 |
O(1)(固定 45 次迭代) |
| 素数判断 (基础) | 单层 for 循环 + 提前返回 | range(2, n) |
一旦整除立即 return False 阻断 |
O(n) |
| 素数判断 (优化) | 单层 for 循环 + 步长跳跃 | range(3, isqrt(n)+1, 2) |
因数对称性剪枝到 √n,跳过全部偶数 |
O(√n) |
四、综合拓展:打印指定区间的全部素数
将上述两个知识点串联起来的最佳实践,就是利用循环结构来批量检测并输出一定范围内的所有素数。例如,寻找 1 到 100 之间的所有素数:
import math
def is_prime(n: int) -> bool:
if n <= 1:
return False
if n == 2:
return True
if n % 2 == 0:
return False
for i in range(3, math.isqrt(n) + 1, 2):
if n % i == 0:
return False
return True
# 查找 1 到 100 的所有素数
primes_under_100 = [num for num in range(1, 101) if is_prime(num)]
print("1 到 100 的素数列表:", primes_under_100)
print(f"共发现 {len(primes_under_100)} 个素数。")
在该示例中,列表推导式 [num for num in range(1, 101) if is_prime(num)] 将外层遍历与函数判断无缝结合。读者可以直接在本地运行这段代码,结果会精确返回 25 个素数。通过九九乘法表掌握循环嵌套与输出控制,通过素数判断掌握条件判断与计算剪枝,初学者便迈出了编写高效 Python 算法代码坚实的第一步。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









