给定两个整数,a和b,返回其最大公约数,gcd公司(a、b)。这可能是第一个已知的算法可以追溯到两千多年前!通常归因于欧几里得.

如果a>b掉期(a,b)而a>0{x=b国防部b=aa=x}返回b

(严格地说,这只适用于自然数;您应该首先使用绝对值a和b…)

很明显,这个算法 终止因为每次经过a被指定为“国防部a”运算,这必然会减少它。a总是非负的,因此可能只发生有限次数的传递。

它的工作方式很简单。每次传球开始时gcd公司a和b的值与gcd公司原始输入。为了说明这一点,我们注意到b国防部a是b减去a倍数的;因此,任何常见的除数a和b是常见的除数a和b的国防部a、 和反之亦然,所以gcd公司s必须相同。在最后一步,它返回b,这正好是正确的!(gcd公司(0,b)=b,因为任何自然数都除以0——这不仅仅是一个诡辩:考虑最后一步,它从b开始,是a的倍数)

请注意,此算法适用于任何戒指,不仅仅是整数第条。

历史上(在某种程度上数学上),欧几里得算法这真的很有趣,因为它仍然是我们今天拥有的最好的算法。事实上,它广泛用于因式分解(请参见因子分解算法)和素性测试,两个现代、快节奏的数学领域。非常令人印象深刻,考虑到它起源放在周围公元前200年.

一些人并不知道,通过几个额外的步骤,您可以欧几里得算法不仅要找到最大公分母 两个整数b条c(c),也包括x个对于其中bx公司+塞浦路斯=。我们这里利用的事实是gcd公司两个(或多个)数字中的最小一个也是正数线性组合.

一个简单的演示,您可以将其转换为C比我能做到的更快:

q个第页x个71    1    01   50    0    12   21    1   -12 8-2 31    5    5   -71    3   -7   101    2   12  -171  -19   27gcd(71,50)=1=(71)(-19)+(50)(27)
每行需要四次快速计算:
  • q个i+1=地板(r)/对i+1)
  • 第页i+1=ri-1型-q个*第页
  • x个i+1=xi-1型-q个*x个
  • i+1=yi-1型-q个*年
当然,r0和r1是b和c,按大小递减

欧几里得算法如果你没有例子。所以我准备了一个。我希望它能有所帮助。

问题:查找最大公约数数字636和483。

解决方案:从本质上讲,这意味着“找到636和483中均匀匹配的最大数”。您可以采取以下步骤:
636=483*1+153/*153是余数636÷483*/483 = 153 * 3 + 24153 =  24 * 6 + 924  =   9 * 2 + 69=6*1+36=3*2+0/*余数=0时停止*/所以3是636和483的GCD。
任何问题、建议或错误,请给我留言。
想知道为什么欧几里得算法有效吗?

我们已经知道任何一对积极的整数s有一个最大的公约数; 诀窍是找到它。

从两个不同的数字开始,n个1n个2,我们可以把它们表示为k1d日k2d日,哪里d日是最大的公约数。从定义最大公约数,k1k2相对质数.

在不失一般性的情况下,我们可以假设k1>k个2> 0.然后我们可以表达k1k2:

k1=c1k2+k个这样的话c(c)1> 0k2>k个> 0.

不仅如此,k相对于k2,因为d日2d日(其中d日2最大公约数k2k)将是的公约数n个1n个2更大的d日,与我们的定义相反。

我们可以反复重复上述步骤:

k2=c2k+k个4
k=ck4+k个5

依此类推,得到一系列级联k是这样的k>ki+1> 0,以及其中kki+1是相对最好的(如果不是,d日ki-1型 那么它就不是相对的素数k).

最终, 我们必须达到这样的话k= 1.

然后km-1个=km-1个k+ 0反向工作,我们可以分配n个=kd日并得到欧几里德算法的传统表示:

n个1=c1n个2+n个
n个2=c2n个+n个4
...
n个m-2个=cm-2个n个m-1个+n个
n个m-1个=cm-1个n个+ 0.

哪里d=n当然,如果n个= 1, n个1n个2相对而言素数。



对原始算法稍作修改,您可以节省一些某些情况下的步骤。由于算法对较小的数字只需较少的步骤,因此您应该使用“最小正余数”每个步骤。也就是说,如果步骤代表:

n个=dki+1*c(c)+达克i+2个

我们也可以说

n个=dki+1*(c)+1) -d(k)i+1-k个i+2个).

自从ki+1> ki+1-k个i+2个> 0,继续执行中的算法ki+1-k个i+2个也会提供正确的结果,并且在任何时候都会保存一个步骤ki+1-k个i+2个<ki+2个


将修改应用于施米克的示例:

636 = 483 * 1 + 153483 = 153 * 3 +  24153 =  24 * 6 +   924=9*3-3/*3小于6*/9=3*3+0/*停止*/
同样,3是636和483的GCD,但我们节省了一步。让我们试试更难的一对数字:
973 = 593 * 1 + 380593=380*1+213380 = 213 * 1 + 167213 = 167 * 1 +  46167 =  46 * 3 +  29 46 =  29 * 1 +  17 29 =  17 * 1 +  12 17 =  12 * 1 +   5 12 =   5 * 2 +   2  5 =   2 * 2 +   12=2*1+0/*不必要的最后一步*/
表明973和593是相对质数。这将变为:
 
973 = 593 * 2 - 213593 = 213 * 3 -  46213 =  46 * 5 -  17 46 =  17 * 3 -   5 17 =   5 * 3 +   2  5 =   2 * 2 +   1  2 =   2 * 1 +   0
保存4个步骤。请注意,第二个中出现的大多数数字序列也出现在第一个序列中,但更早了一步。

最后,还有一个小消息:欧几里德算法的最坏情况斐波那契数列.为什么?系数总是1,余数收缩的时间比其他数长数字。而且他们总是相对优秀的,该死的!


编译时C++中的欧几里德算法,使用递归模板是的,我知道它也完成了在这里但是很多编译器会因为简单的版本而窒息。此版本还使用“最小正余数”快捷方式来保存模板专门化。

#包括<ostream>使用std::ostream;使用std::endl;#如果定义STATIC_CONST_WORKS_THE_WAY_IT_SHOULD#定义MAGIC_NUM(n,value)static const unsigned long n=value#其他////枚举黑客宏//#定义MAGIC_NUM(n,value)枚举n##_{n=value}#结尾模板<无符号长i,无符号长j>结构欧几里得{MAGIC_NUM(较小,(i<j)?i: j));MAGIC_NUM(较大,(i<j)?:j: i);MAGIC_NUM(d,(小于等于0)?较小:1));MAGIC_NUM(r,(小于等于0)?大于%d:0);MAGIC_NUM(r2,较小的-r);磁_数值(lpr,(r2<r)?r2:r);typedef欧几里德<leser,lpr>recur_type;MAGIC_NUM(gcd,(lpr>0)?(lpr>1)?递归类型::gcd:1):较小);磁_数值(lcm,大于*(小于/gcd));静态ostream公告(ostream&os){os<<“euclids<”<<i<<“,”<<j<<“>”<<endl;//os<<“d:”<<d<<endl;//os<<“m:”<<m<<endl;//os<<“r:”<<r<<endl;//os<<“lpr:”<<lpr<<endl;//os<<“gcd:”<<gcd<<endl;//os<<“lcm:”<<lcm<<endl;如果(lpr>0)recur_type::announce(os);返回os;}//宣布};//结构欧几里得

欧几里德算法有一个非常优雅的 递归的定义:
  • 基本情况:GCD(A,0)=A
  • 复发病例:GCD(A,B)=GCD(B,A%B)
这当然会导致单线算法在大多数情况下高级程序设计语言。功能是尾部递归,所以如果你有一个好编译器调用堆栈是建立起来的。

登录登记在这里写点什么或联系作者。