求最大公约数算法

本文介绍了两种求最大公约数的算法:更相减损法和欧几里得辗转相除法。更相减损法源于中国古代数学,通过不断相减直至相等得到最大公约数;欧几里得法通过不断取余,最终较小数能被较大数整除,揭示了算法背后的数学原理。在效率上,辗转相除法通常优于更相减损法,尤其在处理大整数时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前写过一篇关于求素数算法的博文,其中的算法主要是判断出某个数是不是一个素数。本文就来探讨一下有关素数算法的另一个问题——求最大公约数。本文的内容,来自于笔者最近看的两本书里面提及的算法,一本是《计算机是怎样跑起来的》,还有一本是《什么是数学 · 对思想和方法的基本研究》,下面就用代码来实现一遍书中的算法。

更相减损法

更相减损法出自中国古代的数学专著,其原文是

可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。

—— 《九章算术》

这段文言文翻译成白话文,包含了下面四个算法步骤

  1. 如果两个数都是偶数,那就先将它们除以二

  2. 若两个数都是奇数,那么就比较两者大小,用大的数字作被减数,小的数字作减数

  3. 将减法得出的结果与减数作比较,重复上面的步骤

  4. 直到最后两个数相等,那么最大公约数就是最后相等的那个数,或最后相等的数乘以每次约去的2最后的乘积

C语言实现

int gcd(int x, int y)
{
   
    // 任意两个自然数都能同时被1整除
	int gcdNum = 1;
	while (x != y) {
   
        // 如果两个数同时能被2整除,那么都先除以2
		if (x % 2 == 0 && y % 2 == 0) {
   
			x /= 2;
			y /= 2;
			gcdNum *= 2;
		}
		else {
   
			if (x > y)
				x -= y;
			else
				y -= x;
		}
	}
	return gcdNum * x;
}

上述的代码,其实并没有什么优化之处。只要稍作思考就知道,由奇数 - 偶数 = 奇数、偶数 - 奇数 = 奇数这一简单算术规律可知,一旦 x 与 y 其中一个不是偶数了,那么接下来的出现的所有数对都是一奇一偶的形式了,所以也就没有必要每次都去判断 x 和 y 是否同时满足偶数这一条件。

再加上更相减损法中,执行最多的操作是步骤2的减法操作,计算机对于这类计算可以计算地非常快,所以算法可以直接使用一个步骤——减法实现

Python代码实现

def gcd(x, y):
	while x != y:
		if x > y:
			x -= y
		else:
			y -= x
	else:
		return x

欧几里得辗转相除法

两千多年前,欧几里得在其著作《几何原本》中提出了辗转相除法,当时没有那么现代化的数学语言描述,所以他当时用的是几何线段来演示这个算法。

欧几里得的做法是:取两根不同长度的线段,视作两个不同的整数,不断地用其中较短的那条线段,去尽可能地截取较长的那条线段,直到较长的线段被截取成比原来较短线段更短,然后用新的较短的线段去尽可能截取较长的线段,如此重复这一过程,直到较短的线段正好将较长线段截取成整数倍,此时较短的线段长度,就是两者的最大公约数了。

我在维基百科上找到了一张描述这一过程的动态图,很生动直观地体现了这一过程

欧几里得算法(出自维基百科)

关于欧几里得辗转相除法的代数证明如下

  • 前提一:如果 a a a 是任一整数,而 b b b 是任一大于 0 0 0 的整数,那么总能找到一个整数 q q q ,使得等式: a = b q + r a = bq + r a=bq+r 恒成立,其中的整数 r r r 满足: 0 ≤ r &lt; b 0 \le r &lt; b 0r<b
  • 前提二:如果整数
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值