用于GCD无限循环的Java二进制方法

时间:2013-06-04 20:06:50

标签: 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;
        }
        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;

这是我用来完成此操作的代码,调试消息永远打印出来。

有没有办法在它卡住时作弊,或者可能设置例外?

1 个答案:

答案 0 :(得分:1)

问题在于负值 - 当其中一个为负数时,holderNum将始终采用负值(为最小值); holderDem将成为积极的,因此delta等于负数而不是正数等于较小的负数。然后holderDem = abs(delta)更大的积极因素并不断增加。在进入循环之前,你应该取两者的绝对值。

E.g:

holderNum = -1holderDem = 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
等等,等等。