GCD-infinate循环的Java二进制方法

GCD-infinate循环的Java二进制方法,java,infinite-loop,greatest-common-divisor,Java,Infinite Loop,Greatest Common Divisor,我用二进制方法来计算两个分数的GCD,这个方法非常好用,除了我从两个分数中减去某些数字 我假设这是因为,例如,当我从1/6中减去2/15时,GCD有一个重复的数字或类似的东西,尽管我可能是错的 //The following lines calculate the GCD using the binary method if (holderNum == 0) { gcd = holderDem; }

我用二进制方法来计算两个分数的GCD,这个方法非常好用,除了我从两个分数中减去某些数字

我假设这是因为,例如,当我从1/6中减去2/15时,GCD有一个重复的数字或类似的东西,尽管我可能是错的

        //The following lines calculate the GCD using the binary method

        if (holderNum == 0) 
        {
            gcd = holderDem;
        }
        else if (holderDem == 0) 
        {
            gcd = holderNum;
        }
        else if ( holderNum == holderDem)
        {
            gcd = holderNum;
        }

        // Make "a" and "b" odd, keeping track of common power of 2.
        final int aTwos = Integer.numberOfTrailingZeros(holderNum);
        holderNum >>= aTwos;
        final int bTwos = Integer.numberOfTrailingZeros(holderDem);
        holderDem >>= bTwos;
        final int shift = Math.min(aTwos, bTwos);

        // "a" and "b" are positive.
        // If a > b then "gdc(a, b)" is equal to "gcd(a - b, b)".
        // If a < b then "gcd(a, b)" is equal to "gcd(b - a, a)".
        // Hence, in the successive iterations:
        //  "a" becomes the absolute difference of the current values,
        //  "b" becomes the minimum of the current values.
        if (holderNum != gcd)
        {
            while (holderNum != holderDem) 
            {
                    //debuging
                    String debugv3 = "Beginning GCD binary method";
                    System.out.println(debugv3);
                    //debugging
                    final int delta = holderNum - holderDem;
                    holderNum = Math.min(holderNum, holderDem);
                    holderDem = Math.abs(delta);

                    // Remove any power of 2 in "a" ("b" is guaranteed to be odd).
                    holderNum >>= Integer.numberOfTrailingZeros(holderNum);
                    gcd = holderDem;
            }
        }           

        // Recover the common power of 2.
        gcd <<= shift;
//以下几行使用二进制方法计算GCD
if(holderNum==0)
{
gcd=holderDem;
}
else if(holderDem==0)
{
gcd=holderNum;
}
else if(holderNum==holderDem)
{
gcd=holderNum;
}
//将“a”和“b”设为奇数,跟踪2的公共幂。
最终int aTwos=整数。跟踪零的数量(holderNum);
holderNum>>=aTwos;
final int bTwos=整数。跟踪零的数目(holderDem);
holderDem>>=bTwos;
最终整数移位=数学最小值(aTwos、bTwos);
//“a”和“b”是正的。
//如果a>b,那么“gdc(a,b)”等于“gcd(a-b,b)”。
//如果a>=整数。跟踪零的数目(holderNum);
gcd=holderDem;
}
}           
//恢复2的公能。

gcd问题在于负值-当其中一个为负值时,
holderNum
将始终采用负值(即最小值)
holderDem
将变为正数,因此
delta
等于负减去正等于负。然后,
holderDem=abs(delta)
是一个更大的正值,并不断增加。在进入循环之前,您应该获取它们的绝对值

例如:

holderNum=-1
holderDem=6

迭代1:

delta = holderNum - holderDem = -1 - 6 = -7
holderNum = Math.min(holderNum, holderDem) = Math.min(-1, 6) = -1
holderDem = Math.abs(delta) = Math.abs(-7) = 7
迭代2:

delta = holderNum - holderDem = -1 - 7 = -8
holderNum = Math.min(holderNum, holderDem) = Math.min(-1, 7) = -1
holderDem = Math.abs(delta) = Math.abs(-7) = 8

等等等等等等。

你有没有试着打印出一些有用的东西,比如“holderNum”和“holderDem”的值?这样你就可以看到这些数字在做什么,而不是猜测。如何保证“b”是奇数?对于
holderNum
holderDem
的哪些值,它是否进入了无限循环?是的,当我打印这些值时,使用给定的示例,holderNum保持在-3,而holderDem不断增加,1195095是在我强制退出之前得到的值。对于哪些值?这对我很有效,举个例子,比如2/15减去1/6。或者1/1减去1/1。但是如果我在那里放一个断点,它工作得很好,我想它工作得很好?我可以看到那里的问题,但是即使我放进去取Num和Dem的abs值,在循环内或循环外,它仍然无限迭代。我不得不添加
while(holderDem!=0&&holderNum!=holderDem&&holderNum!=0)
holderNum
holderDem
应该是
0
的唯一原因是如果它们以该值开头-在这种情况下,它们应该在开头被捕获(现在我注意到,
if(holderNum!=gcd)
行也应该测试
holderDem
)-或者如果它们在循环开始时相等-在这种情况下,循环应停止。如果你在这段代码开始的时候取绝对值,我不明白为什么它会进入一个无限循环。我也不知道。这真的很奇怪,我认为一些Python进入了我的Java。