LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 8184|回复: 14

[算法]求最大公约数:二进制欧几里德算法(Binary Euclid's Algorithm)

[复制链接]
发表于 2006-2-28 08:06:44 | 显示全部楼层 |阅读模式
zz from:http://www.cut-the-knot.org/blue/binary.shtml

Euclid's algorithm is tersely expressed by the recursive formula
[color="Blue"](1)        gcd(N,M) = gcd(M, N mod M),

where (N mod M) is the remainder of division of N by M. We postulate gcd(N,0) = N in accordance with the end condition of Euclid's algorithm. Our example appears as
        gcd(2322,654) = gcd(654,360) = gcd(360,294) = gcd(294,66) = gcd(66,30) = gcd(30,6) = gcd(6,0) = 6.

Other properties of gcd are expressed in such a similarly concise form

[color="Blue"]   1. gcd(KN, KM) = K gcd(N, M)
   2. If gcd(N,M) = 1 then gcd(N,MK) = gcd(N,K)
   3. gcd(N, M) = gcd(N - M, M)

There are many ways to prove these. For instance, the first and second follow from the Fundamental Theorem of Arithmetic; the second (in a more direct manner) is also a consequence of a generalization of Proposition VII.30 the third one follows from the basic properties of modular arithmetic and division. A binary algorithm for finding gcd(N,M) is based on the following

   1. If N and M are even, gcd(N, M) = 2 gcd(N/2, M/2),
   2. If N is even while M is odd, then gcd(N, M) = gcd(N/2, M),
   3. If both N and M are odd, then (since N-M is even) |N-M| < max(N,M). Replace the largest of the two with |N-M|.

The algorithm is known as binary because, unlike the original one, it does not use general division of integers but only division by 2. Since in a computer numbers are represented in the Binary system anyway, you should not be surprised to learn that there is a special machine instruction that implements division by 2 in a highly efficient manner. This is known as the right shift wherein the rightmost bit is discharged, the remaining bits are shifted one place to the right and the leftmost bit is set to 0.

Another handy operation is a bitwise conjunction &. N & 1 is either 1 or 0 for any integer N. It's 1 iff N is odd. Bitwise conjunction is also implemented in hardware, i.e., as a machine instruction.

The binary algorithm was discovered by R.Silver and J.Tersian in 1962 and has been published by G.Stein in 1967. Convergence of the algorithm, if not obvious, can be shown by induction. Property 3. above assures that induction is applicable.
 楼主| 发表于 2006-2-28 08:10:45 | 显示全部楼层
上述算法的ANSI/C语言实现

  1. unsigned binary_gcd (unsigned x, unsigned y)
  2. {
  3.   unsigned temp;
  4.   unsigned common_power_of_two = 0;
  5.   if (x == 0) return y; /* special cases */
  6.   if (y == 0) return x;
  7.   /* Find the largest power of two
  8.      that divides both x and y. */
  9.   while (((x | y) & 1) == 0)
  10.     {
  11.       x = x >> 1; /* or: "x >>= 1" */
  12.       y = y >> 1;
  13.       ++common_power_of_two;
  14.     }
  15.   while ((x & 1) == 0) x = x >> 1;
  16.   while (y)
  17.     {
  18.       /* x is odd and y is nonzero here. */
  19.       while ((y & 1) == 0) y = y >> 1;
  20.       /* x and y are odd here. */
  21.       temp = y;
  22.       if (x > y) y = x - y;
  23.       else y = y - x;
  24.       x = temp;
  25.       /* Now x has the old value of y, which is odd.
  26.          y is even, because it is the difference of
  27.          two odd
  28.          numbers; therefore it will be right-shifted
  29.          at least once on the next iteration. */
  30.     }
  31.   return (x << common_power_of_two);
  32. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-28 08:24:24 | 显示全部楼层
欧几里德算法自然语言(汉语)描述:

  1. 1 )   若 a = 0 ,则 d ← b ,跳到第 9 步;
  2. 2 )   若 b = 0 ,则 d ← a ,跳到第 9 步;
  3. 3 )   若 a < b ,则交换 a 和 b  ;
  4. 4)    d ← (a MOD b);   
  5. 5 )   a ← b  ;
  6. 6 )   b ← d  ;
  7. 7 )   若 d < 0 ,跳转到第 4 步;
  8. 8 )   d ← b  ;
  9. 9 )  结束。
复制代码


二进制欧几里德算法自然语言(汉语)描述:

  1. 1 )     若 a = 0 ,则 d = b 。转到 1 2;
  2. 2 )     若 b = 0 ,则 d = a 。转到 1 2;
  3. 3 )     令正整数 p = 0;
  4. 4 )     若 a 和 b 都是偶数,则 a ← (a/2),b ← (b/2),p ← p + 1;
  5. 5 )     若 a 和 b 仍都是偶数,转到 4 ;
  6. 6 )     若 a 是偶数,b 是奇数,则 a ← (a/2);
  7. 7 )     若 a 仍是偶数,转到 6 ;
  8. 8 )     若 a 是奇数,b 是偶数,则 b ← (b/2) ;
  9. 9 )     若 b 仍是偶数,转到 8 ;
  10. 1 0 )   若 a 和 b 都不是偶数,则 a ← b ,b ← | a - b |;
  11. 1 1 )   若 b ≠ 0 ,转到 8;
  12. 1 2 )   d ← ax (2的P次方) ;
  13. 1 3 )   结束。
复制代码


证明略
回复 支持 反对

使用道具 举报

发表于 2006-2-28 16:56:56 | 显示全部楼层
不佩服不行的
回复 支持 反对

使用道具 举报

发表于 2006-3-8 07:40:57 | 显示全部楼层
Lolita 要当数学老师吗?
回复 支持 反对

使用道具 举报

发表于 2007-5-19 13:32:19 | 显示全部楼层

这样写会简单些

int gcd(int a, int b)
{
if(b=0) return(a);
gcd(b, a%b);
}
回复 支持 反对

使用道具 举报

发表于 2007-5-21 08:30:29 | 显示全部楼层
本人水平差看不懂了,6 楼写的看得还有点懂,是不是"辗转相除法"的意思啊?
回复 支持 反对

使用道具 举报

发表于 2007-5-22 09:01:20 | 显示全部楼层
对我很有帮助阿
回复 支持 反对

使用道具 举报

发表于 2007-5-22 20:29:42 | 显示全部楼层
是的,这个就是辗转相除法.

初等数论的教材中都会有介绍的.

当然,楼主介绍的也很深刻.
回复 支持 反对

使用道具 举报

发表于 2007-5-25 20:57:28 | 显示全部楼层
辗转相除法,在西方叫欧几里得除法。本人更喜欢wildoxlee兄的 递归 算法,精炼!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表