Java:得到最大的公约数

Alb*_*ert 78 java greatest-common-divisor

我已经看到这样的功能存在BigInteger,即BigInteger#gcd.Java中是否还有其他函数适用于其他类型(int,longInteger)?这似乎是有意义的java.lang.Math.gcd(有各种各样的重载),但它不存在.它在别的地方吗?


(请不要将此问题与"我如何自己实施"这一问题混淆,请!)

Mat*_*att 129

据我所知,没有任何内置的基元方法.但是这样简单的事情应该可以解决问题:

public int GCD(int a, int b) {
   if (b==0) return a;
   return GCD(b,a%b);
}
Run Code Online (Sandbox Code Playgroud)

如果你是这样的话,你也可以单行:

public int GCD(int a, int b) { return b==0 ? a : GCD(b, a%b); }
Run Code Online (Sandbox Code Playgroud)

应该注意的是,两者之间完全没有区别,因为它们编译为相同的字节代码.

  • 它是欧几里德算法......它非常古老且经过验证是正确的.http://en.wikipedia.org/wiki/Euclidean_algorithm (17认同)

Ton*_*nis 69

对于int和long,作为原语,不是真的.对于整数,有可能有人写了一个.

鉴于BigInteger是int,Integer,long和Long的(数学/功能)超集,如果您需要使用这些类型,请将它们转换为BigInteger,执行GCD并将结果转换回来.

private static int gcdThing(int a, int b) {
    BigInteger b1 = BigInteger.valueOf(a);
    BigInteger b2 = BigInteger.valueOf(b);
    BigInteger gcd = b1.gcd(b2);
    return gcd.intValue();
}
Run Code Online (Sandbox Code Playgroud)

  • `BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue()`好多了. (59认同)
  • 如果经常调用此函数(即数百万次),则不应将int或long转换为BigInteger.仅使用原始值的函数可能会快一个数量级.检查其他答案. (4认同)
  • 一些基准测试:/sf/ask/1509962331/ (2认同)

Xor*_*lev 34

或者用于计算GCD的欧几里德算法......

public int egcd(int a, int b) {
    if (a == 0)
        return b;

    while (b != 0) {
        if (a > b)
            a = a - b;
        else
            b = b - a;
    }

    return a;
}
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下,您没有指定您不想要替代实现,因为一个不存在.直到后来你才编辑你的帖子而不是寻找实现.我相信其他人已经充分回答了"不". (11认同)
  • 只是为了澄清:这绝对不是我要求的. (3认同)
  • 如果a非常大而b很小,这将会很慢.'%'解决方案会快得多. (2认同)

Tom*_*ker 11

Jakarta Commons Math就是这样.

ArithmeticUtils.gcd(int p,int q)


Mor*_*rad 11

使用番石榴LongMath.gcd()IntMath.gcd()

  • 有趣的是,Guava不使用Euclidean"modulo"方法,而是使用他们声称速度提高40%的二进制GCD算法.可以肯定地说它非常有效且经过充分测试. (2认同)

Ale*_*xey 11

除非我有番石榴,否则我这样定义:

int gcd(int a, int b) {
  return a == 0 ? b : gcd(b % a, a);
}
Run Code Online (Sandbox Code Playgroud)


lin*_*ava 7

您可以使用这种二进制GCD算法的实现

public class BinaryGCD {

public static int gcd(int p, int q) {
    if (q == 0) return p;
    if (p == 0) return q;

    // p and q even
    if ((p & 1) == 0 && (q & 1) == 0) return gcd(p >> 1, q >> 1) << 1;

    // p is even, q is odd
    else if ((p & 1) == 0) return gcd(p >> 1, q);

    // p is odd, q is even
    else if ((q & 1) == 0) return gcd(p, q >> 1);

    // p and q odd, p >= q
    else if (p >= q) return gcd((p-q) >> 1, q);

    // p and q odd, p < q
    else return gcd(p, (q-p) >> 1);
}

public static void main(String[] args) {
    int p = Integer.parseInt(args[0]);
    int q = Integer.parseInt(args[1]);
    System.out.println("gcd(" + p + ", " + q + ") = " + gcd(p, q));
}
Run Code Online (Sandbox Code Playgroud)

}

来自http://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html


Rob*_*onk 6

如果两个数字都是负数,则此处的某些实现无法正常工作.gcd(-12,-18)是6,而不是-6.

所以应该返回绝对值,例如

public static int gcd(int a, int b) {
    if (b == 0) {
        return Math.abs(a);
    }
    return gcd(b, a % b);
}
Run Code Online (Sandbox Code Playgroud)