108

I have seen that such a function exists for BigInteger, i.e. BigInteger#gcd. Are there other functions in Java which also work for other types (int, long or Integer)? It seems this would make sense as java.lang.Math.gcd (with all kinds of overloads) but it is not there. Is it somewhere else?


(Don't confuse this question with "how do I implement this myself", please!)

Oliv
  • 10,221
  • 3
  • 55
  • 76
Albert
  • 65,406
  • 61
  • 242
  • 386
  • 7
    Why is the accepted answer one that tells you how to implement it yourself - although wrapping an existing implementation? =) – djjeck Jan 18 '13 at 21:36
  • I agree with your observation. GCD should a class with a bunch of overloaded static methods that takes in two numbers and gives it's gcd. And it should be part of the java.math package. – anu May 12 '14 at 19:18

16 Answers16

160

As far as I know, there isn't any built-in method for primitives. But something as simple as this should do the trick:

public int gcd(int a, int b) {
   if (b==0) return a;
   return gcd(b,a%b);
}

You can also one-line it if you're into that sort of thing:

public int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b); }

It should be noted that there is absolutely no difference between the two as they compile to the same byte code.

aioobe
  • 413,195
  • 112
  • 811
  • 826
Matt
  • 7,049
  • 7
  • 50
  • 77
  • As far as I can tell it works fine. I just ran 100,000 random numbers though both methods and they agreed each time. – Tony Ennis Oct 24 '10 at 17:05
  • 22
    It's Euclidean algorithm... It's very old and proven right. http://en.wikipedia.org/wiki/Euclidean_algorithm – Rekin Oct 24 '10 at 17:40
  • Yep, I can kind of see it but I need more time to work through it. I like it. – Tony Ennis Oct 24 '10 at 17:59
  • 1
    @Albert, well you could always try it out with a generic type and see if it works. I dunno just a thought, but the algorithm is there for you to experiment with. As far as some standard library or class, I've never seen one. You will still need to specify when you create the object that it is an int, long, etc.. though. – Matt Oct 24 '10 at 18:19
  • 1
    @Albert, well, although Matt provided an implementation, you yourself could make it work in a, as you put is, "more generic" way, no? :) – Bart Kiers Oct 24 '10 at 19:21
  • @Albert, yes I misunderstood your question, and it seems you misunderstood my reply as well: I know you didn't ask **how** to implement this. But, to answer your question whether this is implemented in Java: it isn't (at least, not the way you are asking for). – Bart Kiers Oct 24 '10 at 19:51
  • @Albert could you give an example? In all languages i've dealt with you have to tell the program what type of something you are working with. It may not be as clear as day and the compiler may take care of that work for you, but I'm pretty sure there is nothing like that. – Matt Oct 24 '10 at 20:19
  • @Albert, I never mentioned '(Java's) generics'. I meant that the overloading of these methods could be done by you yourself (even more so since the algorithm has been posted, even if you were already aware of said algorithm). – Bart Kiers Oct 24 '10 at 20:42
  • @Albert yea, ive gone through that. And you specify types in haskell, So i guess i still don't know what you are talking about. – Matt Oct 25 '10 at 00:13
  • No, hence why i posted one. But you can create a generic one if wanted to. Like stated above, you will have to tell it what it is though when you create an object to use that. public GCD( a, b). GCD newGCD = new GCD(); while this may not be not be 100% correct, as i haven't touched java in years, but this should be someone correct and just to point out you can have a generic type. – Matt Oct 25 '10 at 02:04
  • Big disclaimer on this -- if you have negative numbers, it may return a NEGATIVE GCD! =\ Works, otherwise. =) – HoldOffHunger Jun 17 '17 at 23:20
  • Lol that when you understand Math trick from a piece of a Code faster than from crappy formulas and math calculation examples over the internet! – Martin Krajčírovič Aug 16 '18 at 10:06
98

For int and long, as primitives, not really. For Integer, it is possible someone wrote one.

Given that BigInteger is a (mathematical/functional) superset of int, Integer, long, and Long, if you need to use these types, convert them to a BigInteger, do the GCD, and convert the result back.

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();
}
Ry-
  • 218,210
  • 55
  • 464
  • 476
Tony Ennis
  • 12,000
  • 7
  • 52
  • 73
  • 71
    `BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue()` is much better. – Albert Oct 24 '10 at 18:15
  • 2
    Some benchmarks: https://stackoverflow.com/questions/21570890/java-get-greatest-common-divisor-which-method-is-better – jcsahnwaldt Reinstate Monica Mar 18 '15 at 18:54
  • 6
    If this function is called often (i.e. millions of times) you shouldn't convert int or long to BigInteger. A function using only primitive values will likely be an order of magnitude faster. Check the other answers. – jcsahnwaldt Reinstate Monica Mar 24 '15 at 14:41
  • @Bhanu Pratap Singh To avoid casting or truncation, it's better to use separate methods for int and long. I edited the answer accordingly. – jcsahnwaldt Reinstate Monica Mar 24 '15 at 14:43
  • 1
    This not only doesn't answer the question (where is gcd for int or long in Java) but the proposed implementation is pretty unefficient. This should not be the accepted answer. As far as I know the Java runtime doesn't have it, but it exists in third party libraries. – Florian F Aug 11 '17 at 18:50
34

Or the Euclidean algorithm for calculating the 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;
}
Xorlev
  • 8,561
  • 3
  • 34
  • 36
  • 3
    Just to clarify: This is absolutely not what I was asking for. – Albert Oct 24 '10 at 18:13
  • 14
    In this case, you had not specified that you didn't want alternative implementations since one didn't exist. Only later did you edit your post not looking for implementations. I believe others had answered "no" more than adequately. – Xorlev Oct 24 '10 at 21:56
  • 4
    This would be slow if a is very large and b is small. The '%' solutions would be much faster. – Bruce Feist Oct 25 '16 at 21:26
  • This would slow even if difference between a and b would small. I test this now with a = Long.MAX_VALUE and b = Long.MAX_VALUE - 3 and i wait to result for several minutes – Zhenyria Jul 25 '21 at 13:06
12

Unless I have Guava, I define like this:

int gcd(int a, int b) {
  return a == 0 ? b : gcd(b % a, a);
}
Alexey
  • 9,197
  • 5
  • 64
  • 76
11

Use Guava LongMath.gcd() and IntMath.gcd()

Morad
  • 734
  • 5
  • 14
  • 2
    Interestingly Guava doesn't use the Euclidean "modulo" method but the binary GCD algorithm that they claim to be 40% faster. It is safe to say it is pretty efficient and well-tested. – Florian F Aug 11 '17 at 19:44
  • These links are dead now, it seems the new documentation lives @ https://guava.dev/releases/30.1.1-jre/api/docs/com/google/common/math/package-summary.html – Aly Sep 13 '21 at 03:40
10

Jakarta Commons Math has exactly that.

ArithmeticUtils.gcd(int p, int q)

Robot Monk
  • 107
  • 1
  • 7
Tom Tucker
  • 11,676
  • 22
  • 89
  • 130
7

You can use this implementation of Binary GCD algorithm

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));
}

}

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

linuxjava
  • 141
  • 2
  • 4
  • It's a variation of Stein's algorithm which exploits that on most machines, shifting is a relatively cheap operation. It's a standard algorithm. – Bastian J Mar 09 '18 at 10:04
5

Some implementations here are not working correctly if both numbers are negative. gcd(-12, -18) is 6, not -6.

So an absolute value should be returned, something like

public static int gcd(int a, int b) {
    if (b == 0) {
        return Math.abs(a);
    }
    return gcd(b, a % b);
}
Robot Monk
  • 107
  • 1
  • 7
  • One edge case for this is if both `a` and `b` are `Integer.MIN_VALUE`, you'll get `Integer.MIN_VALUE` back as the result, which is negative. This may be acceptable. The problem being that gcd(-2^31, -2^31)=2^31, but 2^31 can't be expressed as an integer. – Michael Anderson Jul 01 '16 at 02:14
  • I'd also recommend using `if(a==0 || b==0) return Math.abs(a+b);` so that the behaviour is truly symmetric for zero arguments. – Michael Anderson Jul 01 '16 at 02:14
3

we can use recursive function for find gcd

public class Test
{
 static int gcd(int a, int b)
    {
        // Everything divides 0 
        if (a == 0 || b == 0)
           return 0;

        // base case
        if (a == b)
            return a;

        // a is greater
        if (a > b)
            return gcd(a-b, b);
        return gcd(a, b-a);
    }

    // Driver method
    public static void main(String[] args) 
    {
        int a = 98, b = 56;
        System.out.println("GCD of " + a +" and " + b + " is " + gcd(a, b));
    }
}
Alfabravo
  • 7,493
  • 6
  • 46
  • 82
Esann
  • 77
  • 5
2
public int gcd(int num1, int num2) { 
    int max = Math.abs(num1);
    int min = Math.abs(num2);

    while (max > 0) {
        if (max < min) {
            int x = max;
            max = min;
            min = x;
        }
        max %= min;
    }

    return min;
}

This method uses the Euclid’s algorithm to get the "Greatest Common Divisor" of two integers. It receives two integers and returns the gcd of them. just that easy!

Mohsen Mousavi
  • 131
  • 2
  • 8
1

If you are using Java 1.5 or later then this is an iterative binary GCD algorithm which uses Integer.numberOfTrailingZeros() to reduce the number of checks and iterations required.

public class Utils {
    public static final int gcd( int a, int b ){
        // Deal with the degenerate case where values are Integer.MIN_VALUE
        // since -Integer.MIN_VALUE = Integer.MAX_VALUE+1
        if ( a == Integer.MIN_VALUE )
        {
            if ( b == Integer.MIN_VALUE )
                throw new IllegalArgumentException( "gcd() is greater than Integer.MAX_VALUE" );
            return 1 << Integer.numberOfTrailingZeros( Math.abs(b) );
        }
        if ( b == Integer.MIN_VALUE )
            return 1 << Integer.numberOfTrailingZeros( Math.abs(a) );

        a = Math.abs(a);
        b = Math.abs(b);
        if ( a == 0 ) return b;
        if ( b == 0 ) return a;
        int factorsOfTwoInA = Integer.numberOfTrailingZeros(a),
            factorsOfTwoInB = Integer.numberOfTrailingZeros(b),
            commonFactorsOfTwo = Math.min(factorsOfTwoInA,factorsOfTwoInB);
        a >>= factorsOfTwoInA;
        b >>= factorsOfTwoInB;
        while(a != b){
            if ( a > b ) {
                a = (a - b);
                a >>= Integer.numberOfTrailingZeros( a );
            } else {
                b = (b - a);
                b >>= Integer.numberOfTrailingZeros( b );
            }
        }
        return a << commonFactorsOfTwo;
    }
}

Unit test:

import java.math.BigInteger;
import org.junit.Test;
import static org.junit.Assert.*;

public class UtilsTest {
    @Test
    public void gcdUpToOneThousand(){
        for ( int x = -1000; x <= 1000; ++x )
            for ( int y = -1000; y <= 1000; ++y )
            {
                int gcd = Utils.gcd(x, y);
                int expected = BigInteger.valueOf(x).gcd(BigInteger.valueOf(y)).intValue();
                assertEquals( expected, gcd );
            }
    }

    @Test
    public void gcdMinValue(){
        for ( int x = 0; x < Integer.SIZE-1; x++ ){
            int gcd = Utils.gcd(Integer.MIN_VALUE,1<<x);
            int expected = BigInteger.valueOf(Integer.MIN_VALUE).gcd(BigInteger.valueOf(1<<x)).intValue();
            assertEquals( expected, gcd );
        }
    }
}
MT0
  • 143,790
  • 11
  • 59
  • 117
  • Similar to MutableBigInteger.binaryGcd(int,int), unfortunately the latter is not accessible. But cool anyway! –  Mar 16 '16 at 22:44
1

Is it somewhere else?

Apache! - it has both gcd and lcm, so cool!

However, due to profoundness of their implementation, it's slower compared to simple hand-written version (if it matters).

0
/*
import scanner and instantiate scanner class;
declare your method with two parameters
declare a third variable;
set condition;
swap the parameter values if condition is met;
set second conditon based on result of first condition;
divide and assign remainder to the third variable;
swap the result;
in the main method, allow for user input;
Call the method;

*/
public class gcf {
    public static void main (String[]args){//start of main method
        Scanner input = new Scanner (System.in);//allow for user input
        System.out.println("Please enter the first integer: ");//prompt
        int a = input.nextInt();//initial user input
        System.out.println("Please enter a second interger: ");//prompt
        int b = input.nextInt();//second user input


       Divide(a,b);//call method
    }
   public static void Divide(int a, int b) {//start of your method

    int temp;
    // making a greater than b
    if (b > a) {
         temp = a;
         a = b;
         b = temp;
    }

    while (b !=0) {
        // gcd of b and a%b
        temp = a%b;
        // always make a greater than b
        a =b;
        b =temp;

    }
    System.out.println(a);//print to console
  }
}
Gitau Harrison
  • 3,179
  • 1
  • 19
  • 23
0

I used this method that I created when I was 14 years old.

    public static int gcd (int a, int b) {
        int s = 1;
        int ia = Math.abs(a);//<-- turns to absolute value
        int ib = Math.abs(b);
        if (a == b) {
            s = a;
        }else {
            while (ib != ia) {
                if (ib > ia) {
                    s = ib - ia;
                    ib = s;
                }else { 
                    s = ia - ib;
                    ia = s;
                }
            }
        }
        return s;
    }
John Doe
  • 1
  • 1
0

Those GCD functions provided by Commons-Math and Guava have some differences.

  • Commons-Math throws an ArithematicException.class only for Integer.MIN_VALUE or Long.MIN_VALUE.
    • Otherwise, handles the value as an absolute value.
  • Guava throws an IllegalArgumentException.class for any negative values.
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
-3

The % going to give us the gcd Between two numbers, it means:- % or mod of big_number/small_number are =gcd, and we write it on java like this big_number % small_number.

EX1: for two integers

  public static int gcd(int x1,int x2)
    {
        if(x1>x2)
        {
           if(x2!=0)
           {
               if(x1%x2==0)     
                   return x2;
                   return x1%x2;
                   }
           return x1;
           }
          else if(x1!=0)
          {
              if(x2%x1==0)
                  return x1;
                  return x2%x1;
                  }
        return x2;
        } 

EX2: for three integers

public static int gcd(int x1,int x2,int x3)
{

    int m,t;
    if(x1>x2)
        t=x1;
    t=x2;
    if(t>x3)
        m=t;
    m=x3;
    for(int i=m;i>=1;i--)
    {
        if(x1%i==0 && x2%i==0 && x3%i==0)
        {
            return i;
        }
    }
    return 1;
}
  • 3
    This is wrong, e.g. `gcd(42, 30)` should be `6` but it is `12` by your example. But 12 is not a divisor of 30 and neither of 42. You should call `gcd` recursively. See the answer by Matt or look on Wikipedia for the Euclidean algorithm. – Albert Nov 18 '13 at 10:28