【问题标题】:Java binary method for GCD infinate loopGCD无限循环的Java二进制方法
【发布时间】:2013-06-04 20:06:50
【问题描述】:

我正在使用二进制方法来计算两个分数的 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;

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

有没有办法在卡住时作弊,或者设置一个例外?

【问题讨论】:

  • 你有没有试过打印一些有用的东西,比如“holderNum”和“holderDem”的值?这样你就可以看到数字在做什么,而不是猜测它。
  • 如何保证“b”为奇数? holderNumholderDem 的值是多少,是否进入了无限循环?
  • 是的,当我打印出来时,使用给出的示例,holderNum 保持在-3,而 holderDem 不断增加,1195095 是我强制退出之前的位置。
  • 对于什么值?它对我有用。
  • 给出的例子,例如2/15减去1/6。或 1/1 减去 1/1。但是,如果我在那里休息一下,它就可以正常工作,我想这可以吗?

标签: java infinite-loop greatest-common-divisor


【解决方案1】:

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

例如:

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

等等等等等等

【讨论】:

  • 我可以在那里看到问题,但即使我输入了 Num 和 Dem 的 abs 值,在循环中或循环外,它仍然会无限迭代。我必须添加while (holderDem != 0 &amp;&amp; holderNum != holderDem &amp;&amp; holderNum != 0)
  • 很奇怪。 holderNumholderDem 应该永远是 0 的唯一原因是它们是否以该值开头——在这种情况下,它们应该从一开始就被捕获(现在我注意到 if (holderNum != gcd) 行也应该测试 @987654334 @) — 或者如果它们在循环开始时相等 — 在这种情况下循环应该停止。如果您在此代码的开头采用绝对值,我不明白为什么它应该进入无限循环。
  • 我也没有。这真的很奇怪,我认为一些 Python 进入了我的 Java。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
相关资源
最近更新 更多