您的位置:首页 > 运维架构 > Linux

C语言之linux内核实现最大公约数算法

2016-02-17 21:34 465 查看
最大公约数算法,又称欧几里德算法,至今已有几千年的历史了。在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算。

两个整数的最大公约数是能够同时整除它们的最大的正整数。辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的相除余数的最大公约数。

例如,252和105的最大公约数是21(252
= 21 × 12;105 = 21 × 5);

算法原理:

设两数为a、b(b<a),用gcd(a,b)表示a,b的最大公约数,r=a (mod b) 为a除以b以后的余数,k为a除以b的商,即a÷b=k.......r。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。

第一步:令c=gcd(a,b),则设a=mc,b=nc

第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c

第三步:根据第二步结果可知c也是r的因数

第四步:可以断定m-kn与n互质【否则,可设m-kn=xd,n=yd (d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数成为cd,而非c,与前面结论矛盾】

从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。

证毕。

以上步骤的操作是建立在刚开始时r!=0的基础之上的。即m与n亦互质。

我们来看看代码:

一样的,从linux内核中把代码抠出来。


#include <stdio.h>
#include <stdlib.h>
/*
 * swap - swap value of @a and @b    这个宏实现和a和b两个参数之间的交换
 */
#define swap(a, b) \
	do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)

/* Greatest common divisor */
unsigned long gcd(unsigned long a, unsigned long b)
{
	unsigned long r;
       //判断,如果参数a < b 的话就把两数进行交换
	if (a < b)
		swap(a, b);
	while ((r = a % b) != 0) {          //如果两数取模运算不为0,就循环取到0为止
		a = b;//将b的值赋值给a
		b = r;//将r的值赋值给b
	}
	return b; //返回b的值
}
//以上其实就是典型的辗转相除法
int main(void)
{
	printf("%ld\n",gcd(12,18));
	return 0 ;	
}
运行结果:

12和18的最大公约数为6

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: