计算两个整数的最小公倍数的最有效方法是什么?


69

计算两个整数的最小公倍数的最有效方法是什么?

我只是想出了这一点,但是肯定有一些不足之处。

int n=7, m=4, n1=n, m1=m;

while( m1 != n1 ){
    if( m1 > n1 )
        n1 += n;
    else 
        m1 += m;
}

System.out.println( "lcm is " + m1 );

Answers:


137

的最小公倍数(LCM)ab是他们的产品可以通过最大公约数(GCD)划分(即lcm(a, b) = ab/gcd(a,b))。

因此,问题就变成了如何找到gcd?该欧几里德算法是最大公因数一般是如何计算的。经典算法的直接实现是有效的,但是有些变化可以利用二进制算法来做得更好。参见Knuth的“计算机程序设计艺术第2卷,“ Seminumicalical Algorithms”(第4.5.2节)


86
是的,使用GCD的LCM快速且易于编码。一个很小但很重要的细节:为了避免溢出,请像这样计算最终结果:lcm = a / gcd * b而不是lcm = a * b / gcd
Bolo 2010年

7
@Bolo-如果您“担心”溢出,则应该使用long或在其他情况下使用BigInteger。两个int值的LCM可以是long
斯蒂芬·C

14
@Stephen C如果使用Bolo的方法,则可以表示LCM,而不会发生溢出。不必仅将乘法使用较大和较慢的数字类型。
starblue'7

3
@starblue-但是相反,问题是LCM不能表示为int。我们知道一个事实,即对某些价值观mn它不能。我的观点是,如果你担心在计算溢出,你应该担心最后的结果溢出。
斯蒂芬·C

7
@Stephen C可能会发生两个输入整数的顺序为O(N),而它们的LCM的顺序为O(N)。在原始方法中,中间结果的阶数为O(N ^ 2),而在修改后的结果中,中间结果仅为O(N)。示例:p = 2 ^ 31-1 = 2147483647,m = 2 * p,n = 3 * p。它们的LCM = 6 * p,这些数字不是很大(long可以表示最大为2 ^ 63-1 = 9223372036854775807807的整数),但是原始方法仍然会溢出(中间值为6 * p * p)。一个简单的重新排序可以大大提高算法的适用性,不管其类型如何(shortint,或long)。
Bolo 2010年

5

请记住,最小公倍数是最小整数,是两个或多个数字中每个数字的倍数。

如果您要找出三个整数的LCM,请按照下列步骤操作:

  **Find the LCM of 19, 21, and 42.**

为每个数字写素数分解。19是质数。您无需考虑因素19。

21 = 3 × 7
42 = 2 × 3 × 7
19

重复每个素数因子出现在以上任何素数因子分解中的最大次数。

2×3×7×19 = 798

21、42和19的最小公倍数是798。


如果您已经需要素数分解来进行其他计算,则非常好
Dean Brown

不幸的是,找到任意数的素数分解是一个“难题” en.wikipedia.org/wiki/Prime_factor#Cryptographic_applications
Daniel Kats


2

下面的C ++最佳解决方案

#include <iostream>
using namespace std; 
long long gcd(long long int a, long long int b){        
    if(b==0)
        return a;
    return gcd(b,a%b);
}

long long lcm(long long a,long long b){     
    if(a>b)
        return (a/gcd(a,b))*b;
    else
        return (b/gcd(a,b))*a;    
} 

int main()
{
    long long int a ,b ;
    cin>>a>>b;
    cout<<lcm(a,b)<<endl;        
    return 0;
}

1

我不知道它是否经过优化,但可能是最简单的一种:

public void lcm(int a, int b)
{
    if (a > b)
    {
        min = b;
        max = a;
    }
    else
    {
        min = a;
        max = b;
    }
    for (i = 1; i < max; i++)
    {
        if ((min*i)%max == 0)
        {
            res = min*i;
            break;
        }
    }
    Console.Write("{0}", res);
}

1

首先,您必须找到最大的公约数

for(int i=1; i<=a && i<=b; i++) {

   if (i % a == 0 && i % b == 0)
   {
       gcd = i;
   }

}

之后,使用GCD,您可以轻松找到这样的最小公倍数

lcm = a / gcd * b;

从两个数字中的较低者开始向下迭代到零会更快吗?这样,您可以避免遍历整个集合。类似的东西for (int i = a; i >= 0; i--),如果if语句返回true,则可以跳出循环。
美联社

1

这是一种在python中查找两个数字的LCM的高效方法。

def gcd(a, b):
    if min(a, b) == 0:
        return max(a, b)
    a_1 = max(a, b) % min(a, b)
    return gcd(a_1, min(a, b))

def lcm(a, b):
    return (a * b) // gcd(a, b)

0

取两个数中较大者的连续倍数,直到结果是较小数的倍数。

这可能工作。

   public int LCM(int x, int y)
   {
       int larger  = x>y? x: y,
           smaller = x>y? y: x,
           candidate = larger ;
       while (candidate % smaller  != 0) candidate += larger ;
       return candidate;
   }

对于x和y较小的值,这将可以正常工作,将难以缩放。
andand 2010年

Dude,这有助于解决Euclid算法导致堆栈溢出的挑战。我想扩大规模,您只是将它们视为字符串,并具有求模和加法的功能?
Shivam Chawla

0

C ++模板。编译时间

#include <iostream>

const int lhs = 8, rhs = 12;

template<int n, int mod_lhs=n % lhs, int mod_rhs=n % rhs> struct calc {
  calc() { }
};

template<int n> struct calc<n, 0, 0> {
  calc() { std::cout << n << std::endl; }
};

template<int n, int mod_rhs> struct calc<n, 0, mod_rhs> {
  calc() { }
};

template<int n, int mod_lhs> struct calc <n, mod_lhs, 0> {
  calc() { }
};

template<int n> struct lcm {
  lcm() {
    lcm<n-1>();
    calc<n>();
  }
};

template<> struct lcm<0> {
  lcm() {}
};

int main() {
  lcm<lhs * rhs>();
}

0

欧几里得GCD代码段

int findGCD(int a, int b) {
        if(a < 0 || b < 0)
            return -1;

        if (a == 0)
            return b;
        else if (b == 0)
            return a;
        else 
            return findGCD(b, a % b);
    }

1
OP正在寻找LCM
Munim Munna '18

0

2个数字的乘积等于LCM * GCD或HCF。因此,找到LCM的最佳方法是找到GCD并将产品与GCD分开。即,LCM(a,b)=(a * b)/ GCD(a,b)。


GDC?您是说GCD吗?

2
听起来还是现有答案的重复。

0

没有比使用内置函数更有效的方法了!

从Python 3.8lcm()开始,数学库中已添加函数。并且可以通过以下签名来调用:

math.lcm(*integers)

返回指定整数参数的最小公倍数。如果所有参数都不为零,则返回值为最小的正整数,该整数是所有参数的倍数。如果任何参数为零,则返回值为0。不带参数的lcm()返回1。


0

使用欧几里得算法找到gcd,然后计算lcm除以gcd和b的乘积,这对我有用。

int euclidgcd(int a, int b){
        if(b==0)
        return a;
        int a_rem = a % b;
        return euclidgcd(b, a_rem);
        }
    
long long lcm(int a, int b) {
        int gcd=euclidgcd(a, b);
        return (a/gcd*b);
        }

int main() {
      int a, b;
      std::cin >> a >> b;
      std::cout << lcm(a, b) << std::endl;
    return 0;           
    }

-1

最有效的方法来计算LCM - 时间复杂度- O(日志(分(A,B)))

基本公式-LCM(a,b)=(a * b)/ GCD(a,b)

GCD(a,b)的时间复杂度是O(log(min(a(b,b)))

在这里您可以找到C,C ++,C#,Python等代码。单击此处

谢谢 !

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.