【问题标题】:How can I only use 2 variables in Java as with the Python code?如何在 Java 中像 Python 代码一样只使用 2 个变量?
【发布时间】:2020-07-31 20:31:44
【问题描述】:

这个 Python 代码也可以用 Java 代码编写吗? :

def gcd(a, b):
    # Return greatest common divisor using Euclid's Algorithm.
    while b:
        a, b = b, a % b
    return a

print (gcd(210, 45))

这是我迄今为止在 Java 代码中所做的:

private static int gcd(int p, int q) {
    // Return greatest common divisor using Euclid's Algorithm.
    int temp;
    while (q != 0) {
        temp = q;
        q = p % q;
        p = temp;
    }
    return p;
}

System.out.println(gcd(210, 45));

如您所见,Java 代码使用 3 个变量,而 Python 代码仅使用 2 个变量。我还想在 Java 代码中只使用 2 个变量,我想保留 while 循环,我不想使用递归。

还有,为什么 Java 需要比 Python 代码多 1 个变量?除了 Python 代码使用元组这一事实。

【问题讨论】:

  • Java 没有用于并行赋值的语法糖,因此您需要一个临时保存变量来按顺序执行多个赋值而不会丢失信息。
  • 好吧我错了,它直接使用栈来交换元素:stackoverflow.com/questions/21047524/…
  • 嗯......你可以使用一些像这样的诡计:a = a %b; a += b; b = a - b; a -= b;
  • @Dici 这真的很酷。我一直认为它使用了一个临时变量,并且从未在引擎盖下看过它。好评论!
  • @Dici 好吧,但是 that 是如何实现的呢?看起来像with two temporary variables

标签: java python algorithm while-loop modulo


【解决方案1】:

两个变量,但你仍然需要交换。

public static int gcd(int r, int s) {
    while (s != 0) {
        r %= s;
        // swap them
        r ^= s;
        s ^= r;
        r ^= s;
    }
    return r;
}

另一种可能性(但不是Java)是在byte code 中编写一个例程,将其存储在byte[] 数组中并作为Java 方法执行。如果使用内部堆栈可以像在 Python 中一样使用,那么这里应该可以。

【讨论】:

  • 我认为这些答案有点跑题了,更多的是关于交换值,而不是真正设法编写一个只有两个变量的 GCD(对它本身没什么兴趣)
  • 问题的作者说“我想保留while循环,我不想使用递归。”
【解决方案2】:

如何在每个循环迭代中执行两个步骤而不进行交换?

private static int gcd(int p, int q) {
    // Return greatest common divisor using Euclid's Algorithm.
    while (q != 0) {
        p %= q;
        if (p == 0)
           return q;
        q %= p;
    }
    return p;
}

【讨论】:

    【解决方案3】:

    差异的原因是Python有一个元组创建/分解的特性,而Java没有。

    正如其他答案所提到的,您可以使用异或或加法/减法进行整数交换。但是,我怀疑对于像 C 或 Rust 这样的性能平台,这是一种虚假的经济,这种 hack 不会加快速度或减少资源使用。 (不过,如果你只是为了挑战,它是合法的,并且可能是唯一的解决方案)

    另外,我认为 Java 不允许这种技巧用于更一般的对象引用。

    【讨论】:

    • 对同一组随机数进行 100M 次迭代的测试运行,single % op followed by three XOR's 明显快于save, %, restore 版本。后者花费了大约 25% 的时间。我也颠倒了顺序。不是JMH 测试,但增量很重要。在这两种情况下,GCD 都使用了相同的 while 循环。希望看到有人用线束测试这个。
    • 嗯,我在考虑像 C++ 这样的性能平台,而不是 Python,其中大部分负载都在解释器中。我会相应地更新和澄清我的答案。
    • 有趣的是,它对 Java 有帮助,感谢您的检查!
    【解决方案4】:

    纠正我如果我错了,你也可以在java中使用2个变量来做gcd操作。

    private static int gcd(int p, int q) {
        // Return greatest common divisor using Euclid's Algorithm.
        int temp;
        while (p != q) {
            if(p > q)
                p = p - q;
            else
                q = q - p;
        }
        return q;
    }
    

    【讨论】:

    • 这不是直接等价的,因为如果其中一个数字很大 (N) 而另一个数字很小(例如 1),您最终可能会进行大量的减法 (N)。您需要取模 (%) 来避免这个问题。
    【解决方案5】:

    Python 可能会在“异或”运算符之上添加一些合成糖。这是在不使用临时变量的情况下交换两个不同变量的值的按位操作。

    参见下面的 Java 示例:

    a = a^b;
    b = a^b;
    a = a^b;
    

    https://en.wikipedia.org/wiki/XOR_swap_algorithm

    【讨论】:

    • 哈哈不错。关于更一般的交换问题,请注意这仅适用于整数,而 Python 的语法适用于任何类型(事实上,如果 ab 属于不同类型,它也适用)
    【解决方案6】:

    除了给出的示例之外,还有一种众所周知的算法可以在不使用第三个变量的情况下交换两个整数变量 ab

    // given: two int-variables a and b
    a += b;
    b = a - b;
    a -= b
    // result: a and b have been swapped
    

    如果我们现在首先计算a % b并将其分配给a,那么剩下要做的就是交换ab

    // given: two int-variables a and b
    a = a % b;
    a += b;
    b = a - b;
    a -= b
    // result: the new value of a is b, while the new value of b is a % b
    

    如果加法 a + b 溢出,这甚至可以工作,因为它被减法反转。


    顺便说一句:我认为这是一场代码高尔夫。除非有人受到严重的内存限制,否则我不建议使用此解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-04
      • 2021-04-09
      • 2015-08-24
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 2012-01-30
      • 1970-01-01
      相关资源
      最近更新 更多