Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 欧几里德算法是如何工作的?_Java_Algorithm_Greatest Common Divisor - Fatal编程技术网

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=0,那么a=bq,因此b除以b和a。因此gcd(a,b)=b
  • 否则(r>0),我们可以将寻找gcd(a,b)的问题简化为寻找gcd(b,r)的问题,gcd(b,r)是完全相同的数字(因为a,b和r都可以被d整除)
  • 为什么这是一个减少?因为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-这是什么意思?当然,并非所有的数学证明都是建设性的。哥德尔的不完全性定理是关于为什么有些东西不起作用的。