Я видел , что такая функция существует BigInteger
, то есть BigInteger#gcd
. Есть ли в Java другие функции, которые также работают с другими типами ( int
, long
или Integer
)? Кажется, это имело бы смысл java.lang.Math.gcd
(со всеми видами перегрузок), но его там нет. Это где-то еще?
(Пожалуйста, не путайте этот вопрос с "как мне это реализовать сам"!)
java
greatest-common-divisor
Альберт
источник
источник
Ответы:
Для int и long, как примитивов, не совсем. Для Integer, возможно, кто-то написал его.
Учитывая, что 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(); }
источник
BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).intValue()
гораздо лучше.Насколько мне известно, встроенного метода для примитивов нет. Но что-то настолько простое, как это, должно помочь:
public int gcd(int a, int b) { if (b==0) return a; return gcd(b,a%b); }
Вы также можете однострочно, если вам нравятся такие вещи:
public int gcd(int a, int b) { return b==0 ? a : gcd(b, a%b); }
Следует отметить, что абсолютно никакой разницы, поскольку они компилируются в один и тот же байт-код.
источник
Или евклидов алгоритм вычисления НОД ...
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; }
источник
Используйте гуаву
LongMath.gcd()
иIntMath.gcd()
источник
Если у меня нет Guava, я определяю так:
int gcd(int a, int b) { return a == 0 ? b : gcd(b % a, a); }
источник
В Jakarta Commons Math есть именно это.
ArithmeticUtils.gcd (int p, int q)
источник
Вы можете использовать эту реализацию алгоритма двоичного 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)); }
}
Из http://introcs.cs.princeton.edu/java/23recursion/BinaryGCD.java.html
источник
Некоторые реализации здесь работают некорректно, если оба числа отрицательны. 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); }
источник
a
иb
естьInteger.MIN_VALUE
, выInteger.MIN_VALUE
вернетесь в результате, что отрицательно. Это может быть приемлемо. Проблема в том, что gcd (-2 ^ 31, -2 ^ 31) = 2 ^ 31, но 2 ^ 31 не может быть выражено как целое число.if(a==0 || b==0) return Math.abs(a+b);
чтобы поведение было действительно симметричным для нулевых аргументов.мы можем использовать рекурсивную функцию для поиска 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)); } }
источник
Если вы используете Java 1.5 или новее, то это итеративный двоичный алгоритм GCD, который используется
Integer.numberOfTrailingZeros()
для уменьшения количества требуемых проверок и итераций.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; } }
Модульный тест:
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 ); } } }
источник
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; }
Этот метод использует алгоритм Евклида для получения «наибольшего общего делителя» двух целых чисел. Он получает два целых числа и возвращает их gcd. так просто!
источник
Апач!- у него есть и gcd, и lcm, так здорово!
Однако из-за глубины их реализации он медленнее по сравнению с простой рукописной версией (если это имеет значение).
источник
/* 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 } }
источник
Я использовал этот метод, который создал, когда мне было 14 лет.
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; }
источник
Эти функции GCD, предоставляемые Commons-Math и Guava, имеют некоторые отличия.
ArithematicException.class
только дляInteger.MIN_VALUE
илиLong.MIN_VALUE
.IllegalArgumentException.class
отрицательные значения.источник
% Собирается дать нам gcd Между двумя числами это означает: -% или mod of big_number / small_number = gcd, и мы пишем это на java следующим образом
big_number % small_number
.EX1: для двух целых чисел
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: для трех целых чисел
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; }
источник
gcd(42, 30)
должно быть,6
но это12
на вашем примере. Но 12 не делит ни 30, ни 42. Вы должны вызыватьgcd
рекурсивно. См. Ответ Мэтта или поиск алгоритма Евклида в Википедии.