辗转相除法求最大公约数及与更相减损术的对比
计算两个数的最大公约数(Greatest Common Divisor, GCD)是数学和计算机科学中的基础问题。它指两个或多个整数共有约数中最大的一个。掌握高效的求解方法在处理分数化简、密码学算法等领域至关重要。
本文将直接讲解两种经典算法,并提供可立即执行的步骤和代码。
1. 理解核心算法:辗转相除法(欧几里得算法)
辗转相除法基于一个核心原理:两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。 用公式表示,若 $a$ 和 $b$ 是两个正整数,且 $a > b$,则 $gcd(a, b) = gcd(b, a \mod b)$。
这个原理可以递归或循环应用,直到余数为 0,此时的除数就是最大公约数。
具体操作步骤(以计算 gcd(252, 105) 为例):
- 确认较大数
a和较小数b。此处a = 252,b = 105。 - 计算
a除以b的余数r。计算252 ÷ 105, 商为2,余数为252 - 105 * 2 = 42。 - 判断余数
r是否为0。如果r为0,则当前的b就是最大公约数,停止。 - 将
b的值赋予a,将r的值赋予b,然后回到第2步继续。现在a = 105,b = 42。 - 重复计算
105 ÷ 42, 商2, 余数21。余数不为0,所以a = 42,b = 21。 - 重复计算
42 ÷ 21, 商2, 余数0。余数为0,停止。此时的除数b(值为21)就是252和105的最大公约数。
252 和 105 的最大公约数是 21。
2. 理解对比算法:更相减损术
更相减损术出自中国古代数学著作《九章算术》,其核心是“以较数减较数,以多减少”。基本原理是:两个正整数的差与较小数的最大公约数,等于这两个数本身的最动词公约数。 即 $gcd(a, b) = gcd(b, a-b)$(其中 $a > b$)。
具体操作步骤(同样以计算 gcd(252, 105) 为例):
- 确认两个数
a和b。此处a = 252,b = 105。 - 判断
a和b是否相等。如果相等,则这个数就是最大公约数,停止。 - 计算较大数减去较小数的差
d。计算252 - 105 = 147。 - 将差
d与原来较小的数b组成新的一对数。现在新的一对数是147和105。 - 回到第
2步,对147和105继续操作。 - 重复:
147 - 105 = 42, 新一对数变为105和42。 - 重复:
105 - 42 = 63, 新一对数变为63和42。 - 重复:
63 - 42 = 21, 新一对数变为42和21。 - 重复:
42 - 21 = 21, 新一对数变为21和21。 - 判断到两个数相等,均为
21,停止。21就是最大公约数。
3. 方法对比与分析
| 特性 | 辗转相除法(欧几里得算法) | 更相减损术 |
|---|---|---|
| 核心操作 | 取模运算(除法求余) | 减法运算 |
| 收敛速度 | 极快。每一步余数至少减半,接近对数复杂度。 | 较慢。当两数大小接近时,每次仅减去一个较小数。 |
| 计算开销 | 单次取模运算比减法稍复杂。 | 单次减法运算非常简单。 |
| 适用场景 | 通用首选。尤其适合大数计算,效率优势明显。 | 作为理论介绍,或在特定情境(如硬件仅支持减法)下使用。 |
| 优化变种 | 可以结合二进制操作进行优化。 | 《九章算术》原文中包含“半之”的优化步骤,可先判断奇偶,对偶数除以 2 再计算。 |
关键结论:对于绝大多数实际应用,辗转相除法是效率远高于更相减损术的标准解决方案。更相减损术的价值在于其算法思想的历史意义和在特定理论场景中的演示作用。
4. 实用代码示例
以下是两种算法的 Python 实现,可以直接复制运行。
辗转相除法实现:
def gcd_euclidean(a, b):
"""使用辗转相除法(迭代版本)计算最大公约数"""
# 确保 a >= b
while b != 0:
a, b = b, a % b
return a
# 测试
print(gcd_euclidean(252, 105)) # 输出: 21
更相减损术实现(含半之优化):
def gcd_gengxiang(a, b):
"""使用更相减损术(含‘半之’优化)计算最大公约数"""
# 先处理公共的2因子
shift = 0
while ((a | b) & 1) == 0: # 如果 a 和 b 都是偶数
a >>= 1
b >>= 1
shift += 1
# 现在 a 或 b 至少有一个是奇数
while (a & 1) == 0: # 如果 a 是偶数
a >>= 1
while b != 0:
# 确保 b 是偶数,以便不断减半
while (b & 1) == 0:
b >>= 1
# 现在 a 和 b 都是奇数
if a < b:
a, b = b, a
a = a - b
return a << shift # 将之前提取的公因子2乘回去
# 测试
print(gcd_gengxiang(252, 105)) # 输出: 21
使用标准库:
在 Python 中,最简便的方式是使用内置函数 math.gcd。
import math
print(math.gcd(252, 105)) # 输出: 21
对于绝大多数编程任务,直接调用经过高度优化的库函数是最佳实践。理解其背后的算法原理,则有助于在面试、算法设计或特殊环境中做出正确判断。

暂无评论,快来抢沙发吧!