求最大公约数与最小公倍数的算法

时间:2022-05-24 19:03:44

(一)    最大公约数:

所谓“最大公约数”是指两个数(A和B)都能够被C整除,求这个C的最大值问题。在欧几里德的《几何原本》中记载着辗转相除的方法来解决此类问题。此问题的大致思路是:

 

假设存在A和B两个正整数(且A>B),那么令R= A % B,R和B分别取代原来的B和A,重复取余工作,直到R=0(表明那个A就是最大公约数)。

 

其一般算法(伪代码Pseudo Code)如下(A和B不能为0,且必需保证头一次输入A大于B,算法做了修补):

int GYS (int a, int b)

{

如果 (a<b)

{

a <=> b(交换)

}

 

循环

{

余数 = a % b

a = b

b = 余数

}满足条件 (余数<>0);

 

返回 a;

}

 

由于本题的a和b分别通过循环迭代到了自身(上一次的输出成为下一次计算的输入函数),所以可以简化成递归形式(A和B不能为0,且必需保证头一次输入A大于B,算法做了修补):

int GYS (int a, int b)

{

如果 (a<b)

{

a <=> b(交换)

}

 

如果 (b ==0) 返回a

否则 返回 GYS (b, a % b)

}

 

同样地,中国古老的《九章算学》中曾经有过一种叫做“辗转相减”的方法,其大致定义如下:

设有两个数(A,B)且A大于B,令 D = A - B,将D和B再次按照大小代入A和B中,由大数减去小数……这样辗转相减,直到A=B,此时A或者B就是最大公约数。

 

其一般算法如下(A和B不能为0,且必需保证头一次输入A大于B,算法做了修补):

 

int GYS (int a, int b)

{

循环条件满足 ( a<>b)

{

如果 (a<b)

{

a <=> b(交换)

}

 

a = a - b

}

 

输出a或者b都可

}

 

其同样满足递归的条件,现给出递归的一般式:

int GYS (int a, int b)

{

如果 (a<b)

{

a <=> b(交换)

}

 

如果 (a=b) 返回a或者b

否则 返回 GYS (a-b,b)

}

 

补充说一句:或许读者“惊奇”的发现,为什么一般算法对于欧几里德的而言不必将两个数大小调整放到循环体内,而对于中国的算法必须这样做?道理很简单:因为如果一开始A>B,那么A%B的余数肯定不会大于B,所以把B赋值给A,A% B的结果给B自然永远符合A>B的条件;但是A-B的差和B比较不一定B一定大于它,所以还要内部排序,直到满足条件(大数减小数,直到A=B为止)。

 

至于最小公倍数的求法,直接是两个数的乘积除以最大公约数的结果,这里就不给出具体代码了。