求最大公约数
2017-09-14 20:15
239 查看
本文主要归纳了求最大公约数的几种方法,包括遍历法、欧几里得算法、 Stein算法等。
遍历法
这是一种比较直接、简单的方法。思路是:从两个数中选取一个较小的数作为遍历的起点,然后逐步减去1,寻找可能同时被两个数整除的约数。具体实现如下:
欧几里得算法
欧几里得算法,又称为辗转相除法。其应用的原理是:
Gcd(a,b)=Gcd(b,a%b);
解析:
因为 a%b=a-(a/b)*b (1)
所以 假设a,b的一个公约数为c,那么有a%c==0,b%c==0;
我们把(1)式等号右边的式子,由减号分割为两部分,第一部分是a ,显然可以整除c;第二部分是(a/b)*b,因为b可以整除c,所以b与另外一个数的乘积依旧可以整除c,所以(a/b) *b 可以整除b。由此可以说明,a和b的最大公约数与b和a%b的最大公约数相同,以上式子成立。
以下给出欧几里得算法的递归实现:
以下给出欧几里得算法的迭代实现:
扩展的欧几里得算法
已知整数n、m,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式:
nx + my = Gcd(n, m); (1)
由(1)式可得 , n’ x + m’ y = Gcd (n’,m’); (2)
又 n’ = m;
m’ = n % m = n - (n/m)* m;
把n’ 和 m’ 代入 (2)式得
m x + [ n - (n/m)*m ] y= Gcd (n’,m’);
整理得
ny + m (x- (n/m)y)=Gcd (n’,m’);
故 x’ = y;
y’ = x-(n/m)y;
代码如下:
欧几里得算法采用的是辗转相除的方法,在一般情况下效率比较高。但是当在处理大整数时,由于除法运算的存在,该算法的效率大受影响。
Stein算法
采用移位和减的方式来处理数据,没有除法运算,所以在求最大公约数时是比较高效。
Stein算法原理如下:
1.若a和b都是偶数,则记录下公约数2,然后都除2(即右移1位);
2.若其中一个数是偶数,则偶数除2,因为此时2不可能是这两个数的公约数了
3.若两个都是奇数,则a = |a-b|,b = min(a,b),因为若d是a和b的公约数,那么d也是a-b和min(a,b)的公约数。
基于以上的原理,递归算法实现如下:
参考链接:
https://www.cnblogs.com/drizzlecrj/archive/2007/09/14/892340.html
http://blog.csdn.net/workformywork/article/details/16368345
遍历法
这是一种比较直接、简单的方法。思路是:从两个数中选取一个较小的数作为遍历的起点,然后逐步减去1,寻找可能同时被两个数整除的约数。具体实现如下:
int traverse_Gcd(int n,int m){ int i=n>m?m:n; for(;i>=1;i--){ if(n%i==0 && m%i==0){ return i; } } }
欧几里得算法
欧几里得算法,又称为辗转相除法。其应用的原理是:
Gcd(a,b)=Gcd(b,a%b);
解析:
因为 a%b=a-(a/b)*b (1)
所以 假设a,b的一个公约数为c,那么有a%c==0,b%c==0;
我们把(1)式等号右边的式子,由减号分割为两部分,第一部分是a ,显然可以整除c;第二部分是(a/b)*b,因为b可以整除c,所以b与另外一个数的乘积依旧可以整除c,所以(a/b) *b 可以整除b。由此可以说明,a和b的最大公约数与b和a%b的最大公约数相同,以上式子成立。
以下给出欧几里得算法的递归实现:
int Euclidean_GCd(int n,int m){ if(m==0){ return n; } Euclidean_GCd(m,n%m); }
以下给出欧几里得算法的迭代实现:
int Euclidean2_GCd(int n,int m){ if(m==0){ return n; } while(m!=0){ int t=m; m=n%m; n=t; } return n; }
扩展的欧几里得算法
已知整数n、m,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式:
nx + my = Gcd(n, m); (1)
由(1)式可得 , n’ x + m’ y = Gcd (n’,m’); (2)
又 n’ = m;
m’ = n % m = n - (n/m)* m;
把n’ 和 m’ 代入 (2)式得
m x + [ n - (n/m)*m ] y= Gcd (n’,m’);
整理得
ny + m (x- (n/m)y)=Gcd (n’,m’);
故 x’ = y;
y’ = x-(n/m)y;
代码如下:
int Extended_Euclidean_GCd(int n,int m,int* x,int* y){ if(m==0){ *x=1; *y=0; return n; }else{ int r= Extended_Euclidean_GCd(m,n%m,x,y); int t= *x; *x = *y; *y = t - (n/m)* *y; return r; } }
欧几里得算法采用的是辗转相除的方法,在一般情况下效率比较高。但是当在处理大整数时,由于除法运算的存在,该算法的效率大受影响。
Stein算法
采用移位和减的方式来处理数据,没有除法运算,所以在求最大公约数时是比较高效。
Stein算法原理如下:
1.若a和b都是偶数,则记录下公约数2,然后都除2(即右移1位);
2.若其中一个数是偶数,则偶数除2,因为此时2不可能是这两个数的公约数了
3.若两个都是奇数,则a = |a-b|,b = min(a,b),因为若d是a和b的公约数,那么d也是a-b和min(a,b)的公约数。
基于以上的原理,递归算法实现如下:
int Stein_Gcd(int a,int b){ int t; if(a < b){ t = a; a = b; b = t; } if(b == 0) return a; if(a%2==0 && b%2==0){ return 2*Stein_Gcd(a/2,b/2); }else if(a%2==0 && b%2!=0){ return Stein_Gcd(a/2,b); }else if(a%2!=0 && b%2==0){ return Stein_Gcd(a,b/2); }else { return Stein_Gcd(a-b,b); } }
参考链接:
https://www.cnblogs.com/drizzlecrj/archive/2007/09/14/892340.html
http://blog.csdn.net/workformywork/article/details/16368345
相关文章推荐
- Stein算法 求最大公约数
- 求最大公约数的快速算法
- 最大公约数和最小公倍数
- 求最大公约数 Java递归
- 求最大公约数和最小公倍数
- 【整理】辗转相除法求最大公约数算法证明
- 关于一种求最大公约数的算法的分析与证明
- 经典算法(5)- 用二进制方法实现扩展的最大公约数(Extended GCD)
- 求两个数的最大公约数和最大公倍数
- 用C语言求两个数的最大公约数和最小公倍数
- 斐波那契数列的最大公约数定理
- 算法--最大公约数和最小公倍数
- 《算法设计与分析基础》三种求最大公约数的方法C++实现--欧几里德辗转相除、连续整数检测、质因数相乘
- 求两个数的最大公约数(二)
- 12周任务:求四个数的最大公约数(函数)
- 求最大公约数(利用递归)
- 求两数的最大公约数和最小公倍数
- WIKIOI – 1012 最大公约数和最小公倍数问题
- 寻找两个数的最大公约数
- 欧几里德法求最大公约数