用Python循环实现九九乘法表和素数判断
深入讲解如何使用Python中的for循环与while循环实现九九乘法表输出与素数高效判断,涵盖双重循环嵌套、格式控制、break提前退出机制与平方根优化对比。
学习Python基础语法时,循环结构是控制程序重复处理数据的核心工具。九九乘法表和素数判断是两道经典练习题:前者考察如何组织双重循环的层级嵌套与二维排版,后者考察如何在单层循环中结合条件判断、提前终止(break)以及状态标记。本文将分别展开这两道题目的实现步骤、逻辑细节与优化策略,帮助读者掌握循环控制的常见编写模式。
一、用双重嵌套循环输出九九乘法表
九九乘法表呈阶梯状排列,共有9行。第1行有1项,第2行有2项……第9行有9项。这种“多行且每行包含多个递增项目”的规律,非常适合使用两层嵌套的 for 循环来表达。
1. 逻辑拆解与变量定义
要用程序输出阶梯乘法表,关键在于明确外层与内层循环分别负责什么维度:
- 外层循环控制行号(i): 从1递增到9,代表乘法表的第几行。
- 内层循环控制列号(j): 每进入新的一行,列号从1递增到当前行号
i。因为第i行只需要输出到j == i,所以内层上限直接受外层变量i的约束。 - 格式控制: 每一项输出完后不能立即换行,而应当使用制表符(
\t)或空格隔开;只有当整行所有列输出完毕后,才触发一次换行。
2. 完整代码实现
在Python中,range(start, stop) 遵循“左闭右开”规则(包含 start 但不包含 stop)。要产生 1 到 9 的连续整数,必须传入 range(1, 10);同理,内层循环若要取到 i,必须写作 range(1, i + 1)。
# 完整代码:输出九九乘法表
for i in range(1, 10):
for j in range(1, i + 1):
# end="\t" 保证同行的各项之间用制表符隔开,不提前换行
print(f"{j}×{i}={i * j}", end="\t")
# 内层循环执行完毕,输出换行符以开启下一行
print()
终端输出结果示例:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
在默认终端或编辑器中,乘积为一位数与两位数时字符宽度不同。使用制表符 end="\t" 能够利用固定跳格位对齐各列;也可以使用格式化占位符(如 f"{j}×{i}={i*j:<2}")指定最小显示宽度。
二、用循环与分支判断素数
素数(质数)是指在大于1的自然数中,除了1和它自身外,不能被其他自然数整除的数(如 2, 3, 5, 7, 11 等)。根据这一定义,判断一个正整数 n 是否为素数的基本策略是:用从 2 开始的所有可能除数依次去试除 n,如果发现任意一个数能整除 n,说明 n 是合数;若试除了所有候选数均无法整除,则 n 为素数。
1. 试除法与提前退出(break)
在循环检测时,一旦找到某个除数 d 满足 n % d == 0,就已经可以 100% 确认该数不是素数。此时继续检查后面的除数毫无意义,必须使用 break 语句立即终止循环,避免多余的运算开销。
2. Python 特有的 for-else 语法模式
通常情况下,需要定义一个布尔变量(如 is_prime = True)记录状态。而在Python中,for 循环自带一个专属的 else 子句:
- 如果循环正常结束(即遍历完所有元素,中途没有触发
break),则会执行else块中的代码。 - 如果循环是在执行过程中通过
break提前中断的,则会直接跳过else块。
3. 素数判断的基础代码实现
def is_prime_basic(n):
# 基础边界:小于等于1的整数既不是素数也不是合数
if n <= 1:
return False
# 试除区间:从 2 到 n - 1
for d in range(2, n):
if n % d == 0:
# 找到整除因子,立刻判定不是素数并返回
return False
# 如果遍历完毕均未整除,则是素数
return True
# 示例验证
test_numbers = [1, 2, 9, 13, 25, 29]
for num in test_numbers:
result = is_prime_basic(num)
print(f"数值 {num:<2} 是否为素数: {result}")
三、算法对比:全量试除与平方根优化
上述基础实现中,循环范围设定为 range(2, n)。在待测数值较小时,计算耗时差异不大;但当待测数值增大时,两者之间的性能鸿沟会急剧扩大。
1. 数学原理:因子的对称性
如果正整数 $n$ 是合数,必然可以分解为两个因子的乘积:$n = a \times b$。如果 $a$ 和 $b$ 都严格大于 $\sqrt{n}$,那么它们的乘积 $a \times b$ 必然会大于 $\sqrt{n} \times \sqrt{n} = n$,这与 $n = a \times b$ 产生矛盾。因此:
核心结论: 任意合数 $n$ 至少存在一个不大于 $\lfloor\sqrt{n}\rfloor$ 的非平凡因子。如果我们在 $2$ 到 $\lfloor\sqrt{n}\rfloor$ 范围内没有找到任何能够整除 $n$ 的数,那么在大于 $\sqrt{n}$ 的范围内也绝对不可能找到对应的因子。
2. 优化后的高效实现代码
在Python中,可以通过 int(n ** 0.5) + 1 或使用标准库 math.isqrt(n) + 1 来精准获取试除上限。以下是结合了 for-else 结构的高效写法:
import math
def is_prime_optimized(n):
# 排除小于等于1的数
if n <= 1:
return False
# 2 是唯一的偶素数
if n == 2:
return True
# 排除所有大于2的偶数,减少一半的后续循环
if n % 2 == 0:
return False
# 计算平方根上限(含端点)
limit = math.isqrt(n) + 1
# 从3开始,步长为2,只检查奇数除数
for d in range(3, limit, 2):
if n % d == 0:
return False
else:
# 循环正常执行完毕且未触发 break,判定为素数
return True
# 测试较大数字
sample = 10007
print(f"数值 {sample} 是素数吗?回答:{is_prime_optimized(sample)}")
四、常见问题与调试建议
| 常见问题场景 | 典型错误写法 | 正确做法与原因分析 |
|---|---|---|
| 乘法表输出为单列长条 | 漏写 end="\t" |
print() 默认自带换行(end="\n")。在内层循环中必须显式设置 end="\t" 或空格,让同一行的多项保持在同一行显示。 |
| 乘法表缺少最后一行或最后一项 | range(1, 9) 或 range(1, i) |
range() 是左闭右开区间。要取到 9,上限必须写 10;内层要取到 i,上限必须写 i + 1。 |
| 素数判断将 1 误判为素数 | 直接从 range(2, ...) 开始无前置校验 |
根据数学定义,1 既不是素数也不是合数。函数第一步必须使用 if n <= 1: return False 将 1 及其它非正整数直接滤除。 |
| 平方根截断漏判完全平方数 | range(2, int(n**0.5)) |
例如判断 9 时,$\sqrt{9}=3$。若写 range(2, 3),右开区间不会检查 3,导致 9 被误判为素数。必须写 range(2, int(n**0.5) + 1)。 |
五、核心要点总结
九九乘法表与素数判断展示了Python控制流的两大经典应用场景:
- 嵌套控制: 外层循环负责高维度状态变迁(换行、推进大步长),内层循环负责局部细节填充(同排生成、逐个检验)。
- 状态收敛与提前退出: 在批量探测中,一旦满足判定条件应立即
break或return;善用for-else可以精简多余的标记变量。 - 数学优化优先: 算法效率的提升往往来源于对问题数学特性的挖掘(如因子的平方根对称性),远比单纯堆砌硬件算力更为根本。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













