最大公约数的算法

前几天在网上,看见有人问最大公约数的算法,我写了一个,分别给出了C 和汇编(Intel 8086)的代码描述。

首先,让我理解什么是最大公约数?简单的说,最大公约数就是既能整除各数,又为之最大的数,例如,我们小学的时候求两个数的最大公约数的方法通常是先分别求出两个数的约数,也就是说对两个数进行质因数分解,然后再比较两个数的约数集合,在两个约数集合中最大且分别能被两个数整除的数就是我们要求的最大公约数。例如:求自然数P =12, N =36, 我们分别进行质因数分解得 P = 12 = 1 * 2 * 2 *3 N = 36 = 1 * 2 * 2*3* 3 ,所以 P1 = {1,2,3,4,6,12}, N1 = {1,2,3,4,6,9,18,36} ,我们比较这两个集合,得出他们的最大公约数为 12

那么,在这里,我们怎么样才能用计算机求出这个最大公约数呢?当然不能使用上述方法来求,因为,第一描述起来很复杂,第二效率也不高,接着,我们来使用众所周知的递归来描述我们的算法。我们求两个公约数的思想是欧几里德在其《几何算法》中提出的欧几里德算法,又称之为辗转相除法,理论如下: 如果 q r m 除以 n 的商及余数, m= nq + r, gcd(m,n) = gcd(n,r),证明可以参考欧几里德的《几何算法》。在这里不是我们的主要讨论范畴,故略之。

有了上述的理论作为基础,我们就不难描述我们的算法,具体如下:

int  Gcd ( int m, int n)

{

      int intRemain =0;

     

      if n =0 then

         return m;

      else{

   intRemain = m mod n;

   return Gcd(n, intRemain);

}

}

 

     有了算法,转换为具体的语言描述都是水到渠成的事,下面分别给出C/C++的版本和汇编描述的版本:

1) C/C++的版本:

  #include <stdio.h>

/*求最大公因数的函数 */

unsigned int Gcd(unsigned int m,unsigned int n);

int  main( )

{

       unsigned int m =0,n=0;

       printf("Please enter the first value:");

       scanf("%d",&m);

       printf("Please enter the second value:");

       scanf("%d",&n);

 

       printf("You can get the greatest comman divisor is: %d",Gcd(m,n));

       printf("/n");
 

       return 0;

}

  /*最大公因数的函数 */

unsigned int Gcd(unsigned int m,unsigned int n)

{

       unsigned int intRemainder =0;

 

       if(n ==0)

              return m;

       else{

              intRemainder = m % n;

        return Gcd(n, intRemainder);

       }

}

  2) 8086的汇编版本:

;求出两个数的最大公因数

;author:lengxiao_wang  5/2006
 

.386

.Model  Flat

 

ExitProcess  proto near32 stdcall,dwExitCode:DWORD

include io.h
 

cr     equ   0dh

Lf     equ   0ah
 

.stack  4096

.data

prompt1  byte     cr,Lf,"Please input M/'s value: ",0

number1  DWORD    ?

prompt2  byte     cr,Lf,"Please input N/'s value: ",0

number2  DWORD    ?

Message  byte     cr,Lf,"This greatest common divisor is: ",0

gDnumber DWORD    ?

 

.CODE

;----------------------------------------

;  Recursion Function

;----------------------------------------

Gcd    PROC     Near32

;Gcd(integer m,integer n) reutrn eax

       push    ebp

       mov     ebp,esp

       push    edx

       

       cmp     dword ptr[ebp+8],0

       jne     elseMore

       mov     eax,dword ptr[ebp+12]

       jmp     endIfOne

elseMore:

        mov     eax, dword ptr[ebp+12]       

       xor     edx,edx

       div     dword ptr[ebp+8]

       push    dword ptr[ebp+8]

       push    edx

       call    Gcd

       add     esp,8

 

endIfOne:

        pop     edx

        pop     ebp

        ret

Gcd     ENDP

 

 ;==================================================

 ; the program's main part

 ;==================================================

 

 _start:

       

       ;int 3

       output   prompt1

       input    number1,4

       xor      eax,eax

       atoi     number1 

       push     eax

       output   prompt2

       input    number2,4

       atoi     number2

       push     eax

       call     Gcd

       add      esp,8

 

       dtoa    gDnumber,eax

       output  Message

       output  gDnumber

 

       input   number1,4

       INVOKE   ExitProcess,0

 

PUBLIC  _start

END

 

        事实上,程序设计的本质就是建立于算法,因为有了解决实际问题的算法,我们就轻而易举的通过语言去描述我们的问题,所以他们说Nicklaus Wirth 所提出的 程序 = 算法 + 数据结构 的论断在程序设计领域足以类比于爱因斯坦在物理学中所提出的那个经典的推论 E = M*C^2 (任何物质粒子都相当于一定的能量,能量的大小等于该物质的质量与光速的平方之积) 。随着人类需求的发展,算法将在高端技术应用中将会越来越体现出它的威力,而对于一个真正程序员,这通常也是评价他技术修养的一个重要方面之一。

          }       
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值