如何在一组数字上找到GCD,LCM


Answers:


141

我已经使用Euclid算法找到了两个数字的最大公约数。可以迭代以获得更大数量的GCD。

private static long gcd(long a, long b)
{
    while (b > 0)
    {
        long temp = b;
        b = a % b; // % is remainder
        a = temp;
    }
    return a;
}

private static long gcd(long[] input)
{
    long result = input[0];
    for(int i = 1; i < input.length; i++) result = gcd(result, input[i]);
    return result;
}

最小公倍数有些棘手,但最好的方法可能是通过GCD进行减少,可以类似地进行迭代:

private static long lcm(long a, long b)
{
    return a * (b / gcd(a, b));
}

private static long lcm(long[] input)
{
    long result = input[0];
    for(int i = 1; i < input.length; i++) result = lcm(result, input[i]);
    return result;
}

1
在复杂性方面是否有更快的方法?
CinCout 2015年

@binaryBaBa,整数的速度比线性的速度快是不可能的,因为您将不得不跳过一些检查。至于GCD本身,二进制GCD对于任意精度数可能更快,因为它是移位而不是除法。
Jeffrey Hantin

2
@PEMapModder,如果a * b首先被评估,则结果临时肯定几乎大于结果,因此更有可能溢出long。根据定义,gcd(a, b)ab均分,因此我们可以在相乘之前进行除法并避免这种情况。如果使用BigInteger,则采用相同的逻辑,除了避免溢出以外,您通过使数字更小来减少计算开销。
杰弗里·汉汀

1
@Kagaratsch,这两种情况之间的实际差异可忽略不计;long是基元而不是类,因此不能有堆分配。像样的运行时会自动重用局部变量空间,就像在循环外声明它一样,甚至在短暂的生存期内将其填充到寄存器中,而不是分配局部变量空间。在循环内声明它(至少对读者而言)也表明,它的值不需要在迭代中保留。
杰弗里·汉汀

2
最后两个编辑根本没有意义!最后一个函数不计算gcd,但计算lcm。
Qw3ry

25

有一个针对GCD的Euclid算法

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

顺便说一句,a并且b应该大于或等于0,并且LCM =|ab| / GCF(a, b)


13

没有内置功能。您可以使用Euclid算法找到两个数字的GCD 。

对于一组数字

GCD(a_1,a_2,a_3,...,a_n) = GCD( GCD(a_1, a_2), a_3, a_4,..., a_n )

递归地应用它。

与LCM相同:

LCM(a,b) = a * b / GCD(a,b)
LCM(a_1,a_2,a_3,...,a_n) = LCM( LCM(a_1, a_2), a_3, a_4,..., a_n )

2
BigInteger类具有gcd方法。+1用于回答一组整数而不是一对整数的问题。
总统詹姆斯·波尔克(James K. Polk)2010年

10

如果您可以使用Java 8(并且确实愿意),则可以使用lambda表达式从功能上解决此问题:

private static int gcd(int x, int y) {
    return (y == 0) ? x : gcd(y, x % y);
}

public static int gcd(int... numbers) {
    return Arrays.stream(numbers).reduce(0, (x, y) -> gcd(x, y));
}

public static int lcm(int... numbers) {
    return Arrays.stream(numbers).reduce(1, (x, y) -> x * (y / gcd(x, y)));
}

我以Jeffrey Hantin的回答为导向,但是

  • 从功能上计算gcd
  • 使用varargs-Syntax以获得更简单的API(我不确定过载是否可以正常工作,但是在我的机器上可以)
  • numbers-Array的gcd转换为函数语法,该语法更紧凑并且IMO更易于阅读(至少如果您习惯于函数编程)

由于额外的函数调用,这种方法可能会稍微慢一些,但是对于大多数用例而言,这可能根本不重要。


非常干净的喜欢它
Spets 2016年

4
int gcf(int a, int b)
{
    while (a != b) // while the two numbers are not equal...
    { 
        // ...subtract the smaller one from the larger one

        if (a > b) a -= b; // if a is larger than b, subtract b from a
        else b -= a; // if b is larger than a, subtract a from b
    }

    return a; // or return b, a will be equal to b either way
}

int lcm(int a, int b)
{
    // the lcm is simply (a * b) divided by the gcf of the two

    return (a * b) / gcf(a, b);
}

这是欧几里得算法的实现。要找到两个数字的GCF,请在两个数字不相等的情况下从较小的数字中减去较大的数字。例如:找到6和10的GCF:10 6 // 10大于6,因此从10​​中减去6;4 6 // 6现在大于4,所以从10中减去4;4 2 // 4大于2,因此从4中减去2;2 2 //现在两个数字相等,那就是GCF;数学中的LCM只是第一个数字乘以第二个数字除以其GCF。
user3026735

这也是的真正缓慢的实现gcf。使用%会使事情变得更快(并使这与其他两个答案没有什么不同)。
Teepeemm 2014年

2
int lcmcal(int i,int y)
{
    int n,x,s=1,t=1;
    for(n=1;;n++)
    {
        s=i*n;
        for(x=1;t<s;x++)
        {
            t=y*x;
        }
        if(s==t)
            break;
    }
    return(s);
}

1

使用Java 8,有更多优雅且实用的方法可以解决此问题。

LCM:

private static int lcm(int numberOne, int numberTwo) {
    final int bigger = Math.max(numberOne, numberTwo);
    final int smaller = Math.min(numberOne, numberTwo);

    return IntStream.rangeClosed(1,smaller)
                    .filter(factor -> (factor * bigger) % smaller == 0)
                    .map(factor -> Math.abs(factor * bigger))
                    .findFirst()
                    .getAsInt();
}

GCD:

private static int gcd(int numberOne, int numberTwo) {
    return (numberTwo == 0) ? numberOne : gcd(numberTwo, numberOne % numberTwo);
}

当然,如果一个参数为0,则这两种方法均无效。


为什么您对lcm进行编码如此复杂?它更短并且更不容易出错,从而减少了到gcd的lcm。如果一个参数为零,则您的gcd算法确实起作用。
Qw3ry

0

gcd您cad做如下:

    String[] ss = new Scanner(System.in).nextLine().split("\\s+");
    BigInteger bi,bi2 = null;
    bi2 = new BigInteger(ss[1]);
    for(int i = 0 ; i<ss.length-1 ; i+=2 )
    {
        bi = new BigInteger(ss[i]);
        bi2 = bi.gcd(bi2);
    }
    System.out.println(bi2.toString());

0

基本上是在一组数字上找到gcd和lcm,您可以使用以下公式,

LCM(a, b) X HCF(a, b) = a * b

同时,在Java中,您可以使用euclid的算法来查找gcd和lcm,如下所示

public static int GCF(int a, int b)
{
    if (b == 0)
    {
       return a;
    }
    else
    {
       return (GCF(b, a % b));
    }
}

您可以参考资源以找到有关euclid算法的示例。


0
public class HcfLcm {
    public static void main(String[] args) {
        System.out.println("HCF: "+ getHcf(20, 15)); //5
        System.out.println("LCM: "+ getLcm2(20, 15)); //60
    }

    private static Integer getLcm2(int n1, int n2) {
        int lcm = Math.max(n1, n2);
        // Always true
        while (true) {
            if (lcm % n1 == 0 && lcm % n2 == 0) {
                break;
            }
            ++lcm;
        }
        return lcm;
    }

    private static Integer getLcm(int i, int j) {
        int hcf = getHcf(i, j);
        return hcf * i/hcf * j/hcf; // i*j*hcf
    }

    private static Integer getHcf(int i, int j) {
        while(i%j != 0) {
            int temp = i%j;
            i = j;
            j = temp;
        }
        return j;
    }
}

-1

导入java.util.Scanner; 公共课程Lcmhcf {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    // TODO code application logic here
    Scanner scan = new Scanner(System.in);
    int n1,n2,x,y,lcm,hcf;
    System.out.println("Enter any 2 numbers....");
    n1=scan.nextInt();
    n2=scan.nextInt();
    x=n1;
    y=n2;

    do{
       if(n1>n2){
         n1=n1-n2;
       }
       else{
         n2=n2-n1;
       }
     } while(n1!=n2);
     hcf=n1;
     lcm=x*y/hcf;
     System.out.println("HCF IS = "+hcf);
     System.out.println("LCM IS = "+lcm);

     }
 }
//## Heading ##By Rajeev Lochan Sen

欢迎来到SO。请仔细检查您的代码格式。
理查德·埃里克森

-1
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n0 = input.nextInt(); // number of intended input.
        int [] MyList = new int [n0];

        for (int i = 0; i < n0; i++)
            MyList[i] = input.nextInt();
            //input values stored in an array
        int i = 0;
        int count = 0;
            int gcd = 1; // Initial gcd is 1
            int k = 2; // Possible gcd
            while (k <= MyList[i] && k <= MyList[i]) {
                if (MyList[i] % k == 0 && MyList[i] % k == 0)
                    gcd = k; // Update gcd
                k++;
                count++; //checking array for gcd
            }
           // int i = 0;
            MyList [i] = gcd;
            for (int e: MyList) {
                System.out.println(e);

            }

            }

        }

嗨,欢迎来到Stack Overflow。感谢您发布该问题的答案,但是通常仅包含代码的答案对人们没有太大帮助。有关良好答案的示例,请参见接受的答案。请参阅我如何写一个好的答案?欲获得更多信息。
Adrian Sanguineti

-1
import java.util.*;
public class lcm {
    public static void main(String args[])
    {
        int lcmresult=1;
        System.out.println("Enter the number1: ");
        Scanner s=new Scanner(System.in);
        int a=s.nextInt();
        System.out.println("Enter the number2: ");
        int b=s.nextInt();
        int max=a>b?a:b;
        for(int i=2;i<=max;i++)
        {
            while(a%i==0||b%i==0)
            {
                lcmresult=lcmresult*i;
                if(a%i==0)
                    a=a/i;
                if(b%i==0)
                    b=b/i;
                if(a==1&&b==1)
                    break;
            }
        }
    System.out.println("lcm: "+lcmresult);
}
}

-1
int lcm = 1;
int y = 0;
boolean flag = false;
for(int i=2;i<=n;i++){
            if(lcm%i!=0){
                for(int j=i-1;j>1;j--){
                    if(i%j==0){
                        flag =true;
                        y = j;
                        break;
                    }
                }
                if(flag){
                    lcm = lcm*i/y;
                }
                else{
                    lcm = lcm*i;
                }
            }
            flag = false;
        }

在这里,第一个for循环用于获取从“ 2”开始的每个数字。如果语句检查数字(i)是否除以lcm,则跳过该数字。如果没有,那么下一个for循环就是寻找一个no。如果发生这种情况,可以将数字除以(i),我们不需要否。我们只想要它的额外因素。所以在这里,如果该标志为真,则意味着已经存在一些否定因素。以厘米为单位的“ i”。因此我们将这些因子相除,然后将多余的因子乘以lcm。如果该数字不能被其先前的任何数字整除。然后只需将其乘以lcm。


您好,欢迎来到该网站。尽管此代码可以回答问题,但最好包含一些有关其工作方式和用法的解释。此外,我看不到这个答案如何增加此问答,因为已经有答案涵盖了对该问题的充分理解和测试的解决方案。
Radiodef '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.