最大公约数:辗转相除法 和 Stein算法
1, 辗转相除法原理:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数。
证明:
设两数为a、b(b<a),用gcd(a,b)表示a,b的最大公约数,r=a mod b 为a除以b以后的余数,辗转相除法即是要证明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)。
2, Stein算法
1) 如果A=0,B是最大公约数,算法结束
2) 如果B=0,A是最大公约数,算法结束
3) 设置A1 = A、B1=B和C1 = 1
4) 如果An和Bn都是偶数,则An+1 =An /2,Bn+1 =Bn /2,Cn+1 =Cn *2(注意,乘2只要把整数左移一位即可,除2只要把整数右移一位即可)
5) 如果An是偶数,Bn不是偶数,则An+1 =An /2,Bn+1 =Bn ,Cn+1 =Cn (很显然啦,2不是奇数的约数)
6) 如果Bn是偶数,An不是偶数,则Bn+1 =Bn /2,An+1 =An ,Cn+1 =Cn (很显然啦,2不是奇数的约数)
7) 如果An和Bn都不是偶数,则An+1 =|An -Bn|,Bn+1 =min(An,Bn),Cn+1 =Cn
8) n++,转4
最小公倍数:两数乘积除以最大公约数
#include <stdio.h> int gcd_ZhanZhuanXiangChu(int a, int b) { int n, m, r; if (a > b) { m = a; n = b; } else { m = b; n = a; } r = m%n; while(r != 0) { m = n; n = r; r = m % n; } return n; } int gcd_Stein(int a, int b) { int m = 0, n = 0; if (a == 0) { return b; } if (b == 0) { return a; } if ((a%2 == 0) && (b%2 == 0)) { return 2 * gcd_Stein(a/2, b/2); } if (a%2 == 0) { return gcd_Stein(a/2, b); } if (b%2 == 0) { return gcd_Stein(a, b/2); } if (a > b) { m = a; n = b; } else { m = b; n = a; } return gcd_Stein((m-n)/2, n); } int main() { int a[]={120, 36, 56,17,90}; int b[]={84 , 12, 36,66,100}; int i = 0, c = 0; printf("Calc Greatest Common Divisor and Least Common Multiple\n"); printf("Test Zhan Zhuan Xiang Chu ============== \n"); for (i = 0; i < 5; i++) { c = gcd_ZhanZhuanXiangChu(a[i], b[i]); printf("a=%d and b=%d gcd=%d lcm=%d\n", a[i], b[i], c, a[i]*b[i]/c); } printf("\nTest Stein ================= \n"); for (i = 0; i < 5; i++) { c = gcd_Stein(a[i], b[i]); printf("a=%d and b=%d, gcd=%d lcm=%d\n", a[i], b[i], c, a[i]*b[i]/c); } scanf("%d", &i); return 0; }