【问题标题】:How to find GCD, LCM on a set of numbers如何在一组数字上找到 GCD、LCM
【发布时间】:2021-11-17 01:57:42
【问题描述】:

在一组数字上计算最大公约数和最小公倍数的最简单方法是什么?可以使用哪些数学函数来查找此信息?

【问题讨论】:

    标签: java math greatest-common-divisor lcm


    【解决方案1】:

    我使用Euclid's algorithm 来找到两个数字的最大公约数;可以通过迭代得到更大数字集的 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;
    }
    

    最小公倍数有点棘手,但最好的方法可能是reduction by the 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;
    }
    

    【讨论】:

    • 在复杂性方面有没有更快的方法?
    • @binaryBaBa,在整数数量上比线性快是不可能的,因为你必须跳过检查一些。至于 GCD 本身,binary GCD 对于任意精度的数字可能更快,因为它是移位而不是除法。
    • @PEMapModder,如果首先评估a * b,则生成的临时值几乎肯定大于结果,因此更有可能溢出long。根据定义gcd(a, b) 均分ab,所以我们可以在相乘之前先除以避免这种情况。如果使用 BigInteger,同样的逻辑也适用,除了避免溢出之外,您通过保持数字更小来减少计算开销。
    • @Kagaratsch,这两种情况之间的实际差异可以忽略不计; long 是一个原语而不是一个类,所以不能有堆分配。一个体面的运行时会自动重用局部变量空间,就好像它在循环外声明一样,或者甚至在其短暂的生命周期内将其填充到寄存器中,而不是分配局部变量空间。在循环中声明它也澄清了(至少对读者来说)它的值不需要在迭代中保留。
    • 最后两次编辑完全没有意义!最后一个函数不计算 gcd,而是计算 lcm。
    【解决方案2】:

    GCD 有一个Euclid's algorithm

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

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

    【讨论】:

      【解决方案3】:

      它没有内置功能。您可以使用Euclid's algorithm 找到两个数字的 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 )
      

      【讨论】:

      • BigInteger 类有一个 gcd 方法。 +1 用于回答一组整数而不是一对整数的问题。
      【解决方案4】:

      如果您可以使用 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's answer,但是

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

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

      【讨论】:

      • 很干净很喜欢
      【解决方案5】:
      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。
      • 这也是gcf 的一个非常慢的实现。使用 % 会使事情变得更快(这与其他两个答案没有什么不同)。
      【解决方案6】:
      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);
      }
      

      【讨论】:

        【解决方案7】:

        在 Java 8 中,有更优雅、更实用的方法来解决这个问题。

        液晶模组:

        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编码这么复杂?将 lcm 减少到 gcd 会更短且更不容易出错。如果一个参数为零,您的 gcd 算法确实有效。
        【解决方案8】:

        对于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());
        

        【讨论】:

          【解决方案9】:
          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;
              }
          }
          

          【讨论】:

            【解决方案10】:

            基本上可以使用下面的公式在一组数字上找到 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));
                }
            }
            

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

            【讨论】:

              【解决方案11】:

              导入 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。请仔细检查您的代码格式。
              【解决方案12】:
              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。感谢您发布此问题的答案,但仅包含代码的答案通常对人们没有太大帮助。请参阅接受的答案以获取良好答案的示例。请参阅How do I write a good answer? 了解更多信息。
              【解决方案13】:
              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);
              }
              }
              

              【讨论】:

                【解决方案14】:
                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' 开始的每个数字。然后 if 语句检查 number(i) 是否除以 lcm 如果它是,那么它跳过那个 no。如果没有,那么下一个 for 循环是为了找到一个否。如果发生这种情况,它可以将数字(i)除以我们不需要那个数字。我们只想要它的额外因素。所以在这里,如果标志为真,这意味着已经有一些因素为否。 '我' 在 lcm。所以我们除以这些因子并将额外的因子乘以 lcm。如果该数字不能被其前一个数字整除。然后当简单地将它乘以 lcm。

                【讨论】:

                • 您好,欢迎来到本站。虽然这段代码可以回答这个问题,但最好包括一些关于它如何工作以及如何使用它的解释。此外,我看不出这个答案如何为这个问答增加任何内容,因为已经有答案涵盖了这个问题的易于理解和经过充分测试的解决方案。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-09-09
                相关资源
                最近更新 更多