Java 欧几里德算法是如何工作的?
我刚刚在课堂讲稿中找到了计算最大公约数的算法:Java 欧几里德算法是如何工作的?,java,algorithm,greatest-common-divisor,Java,Algorithm,Greatest Common Divisor,我刚刚在课堂讲稿中找到了计算最大公约数的算法: public static int gcd( int a, int b ) { while (b != 0) { final int r = a % b; a = b; b = r; } return a; } 因此,r是将b除以a时的余数(得到mod)。然后将b分配给a,剩余的分配给b,并返回a。我一辈子都看不出这是怎么回事 然后,显然这个算法并不适用于所有情况,然后必须使
public static int gcd( int a, int b ) {
while (b != 0) {
final int r = a % b;
a = b;
b = r;
}
return a;
}
因此,r是将b除以a时的余数(得到mod)。然后将b分配给a,剩余的分配给b,并返回a。我一辈子都看不出这是怎么回事
然后,显然这个算法并不适用于所有情况,然后必须使用这个算法:
public static int gcd( int a, int b ) {
final int gcd;
if (b != 0) {
final int q = a / b;
final int r = a % b; // a == r + q * b AND r == a - q * b.
gcd = gcd( b, r );
} else {
gcd = a;
}
return gcd;
}
我不明白这背后的原因。我通常会使用递归,并且擅长Java,但这是我无法做到的。请帮忙?他们是同等的。首先要注意的是,第二个程序中根本没有使用
q
。另一个区别是迭代与递归
至于它为什么有效,上面链接的维基百科页面是好的。第一个示例特别有效地直观地传达了“为什么”,下面的动画演示了“如何”。鉴于“q”从未被使用过,我看不出普通迭代函数和递归迭代函数之间有什么区别。。。两者都有
gdc(first number, second number)
as long as (second number > 0) {
int remainder = first % second;
gcd = try(second as first, remainder as second);
}
}
除非尝试将其应用于非整数,否则该算法在哪些情况下会失败
(有关详细信息,请参见)这篇文章包含了一个解释,但很难立即找到它(此外,过程+证明并不总是回答“为什么它有效”的问题)
基本上可以归结为这样一个事实:对于两个整数a,b(假设a>=b),总是可以写出a=bq+r,其中r
如果d=gcd(a,b),那么我们可以写出a=ds和b=dt。所以我们有ds=qdt+r。因为左手边可以被d整除,所以右手边也必须被d整除。既然qdt可以被d整除,那么结论是r也可以被d整除
总结:我们有a=bq+r,其中r
由于a>=b>r,我们有两种情况:
现在,r=a%b有望解释您的代码。这里有一篇有趣的博文: 在讨论欧几里德算法背后的许多直觉时,它是用JavaScript实现的,但我相信,如果有人想要,将代码转换为Java并不困难。是我发现的一个非常有用的解释 对于那些懒得打开它的人,它是这么说的: 考虑一个例子,当您必须找到(30841424)的GCD时。假设d是GCD。意思是d | 3084和d | 1424(用符号“|”表示“除数”) 因此d |(3084-1424)。现在,我们将尽可能减少这些可以被d整除的数字(在本例中是3084和1024),这样我们就可以得到0作为其中一个数字。记住GCD(a,0)是a 自d |(3084-1424)以来,d |(3084-2(1424)) 意思是d|236。
提示:(3084-2*1424=236) 现在忘掉初始数,我们只需要解d,我们知道d是除236,1424和3084的最大数。所以我们使用较小的两个数字继续,因为它会将问题收敛到0 d | 1424和d | 236意味着d |(1424-236)。 所以,d |(1424-6(236))=>d | 8 现在我们知道,d是最大的数,除以82361424和3084。再拿较小的两个,我们有 d | 236和d | 8,这意味着d |(236-8)。 因此,d |(236-29(8))=>d | 4 可被d整除的数字列表再次增加并收敛(数字越来越小,接近0)。现在,d是除以4,823614243084的最大数 采取同样的步骤 d | 8和d | 4表示d |(8-4)。 所以,d |(8-2(4))=>d | 0 可被d整除的数字列表现在是0、4、8、236、1484、3084。 (a,0)的GCD始终为a。所以,一旦你把0作为两个数字中的一个,另一个数字就是原始两个和所有介于两者之间的数字的gcd 这正是您的代码所做的。您可以将终端条件识别为GCD(a,0)=a
另一步是找到这两个数字的剩余部分,并选择该数字和前两个数字中较小的一个作为新数字 你试过用谷歌搜索吗?这里有一个很好的解释:@Luc-这是什么意思?当然,并非所有的数学证明都是建设性的。哥德尔的不完全性定理是关于为什么有些东西不起作用的。