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

far*_*ich 58 math

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

我想出了这个,但它确实留下了一些不足之处.

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 );
Run Code Online (Sandbox Code Playgroud)

Joh*_*ook 114

最小公倍数(lcm)ab它们的乘积除以它们的最大公约数(gcd)(即lcm(a, b) = ab/gcd(a,b)).

那么,问题就变成了,如何找到gcd?该欧几里德算法是最大公因数一般是如何计算的.经典算法的直接实现是有效的,但有些变体利用二进制算法做得更好.参见Knuth的" 计算机程序设计的艺术 " 第2卷,"研究数学算法"§4.5.2.

  • 是的,使用GCD的LCM快速且易于编码.一个小而重要的细节:为了避免溢出,计算最终结果如下:`lcm = a/gcd*b`而不是`lcm = a*b/gcd`. (70认同)
  • @Stephen C使用Bolo的方法,如果可以表示LCM,则可以在没有溢出的情况下计算LCM.没有必要仅为乘法使用更大和更慢的数字类型. (12认同)
  • @Bolo - 如果你"担心"溢出,你应该使用`long`或在其他情况下甚至是'BigInteger`.两个`int`值的LCM可能是`long`. (5认同)
  • @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 = 9223372036854775807的整数),但原始方法无论如何都会溢出(中间值为6*p*p).无论类型("short","int"或"long")如何,简单的重新排序都可以极大地提高算法的适用性. (5认同)
  • @Stephen C 当然,对于固定大小的整数,大多数操作的结果可能会溢出。这是给定的,人们总是必须选择适当大小的数字类型,以免发生溢出。关键是,使用 Bolo 的方法,LCM 的内部计算不会溢出。 (3认同)
  • @starblue - 但相反,问题中没有任何内容可以将LCM*表示为"int".而且我们知道一个事实,对于某些"m"和"n"的值,它不能.我的观点是,如果您担心计算中出现溢出,您应该*担心最终结果溢出. (2认同)
  • @Bolo - 是的,但是***将结果的类型改为`long`将进一步增加其适用性*.找到小于'2 ^ 31`的互质`m`和`n`并且`LCM(m,n)`(即`m*n`)大于'2 ^ 31`并不难. (2认同)
  • @Stephen C - 但你一直主张使用 long 并且似乎对 Bolo 的非常重要的改进感到不屑,它避免了许多溢出情况。波洛是对的。 (2认同)

小智 5

记住,最小公倍数是最小整数,它是两个或多个数字中每一个的倍数.

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

  **Find the LCM of 19, 21, and 42.**
Run Code Online (Sandbox Code Playgroud)

为每个数字写出素数因子分解.19是素数.你不需要考虑因素19.

21 = 3 × 7
42 = 2 × 3 × 7
19
Run Code Online (Sandbox Code Playgroud)

重复每个素数因子在上述任何主要因子分解中出现的最大次数.

2×3×7×19 = 798

21,42和19的最小公倍数是798.

  • 不幸的是,找到任意数字的素因数分解是一个“难题”https://en.wikipedia.org/wiki/Prime_factor#Cryptographic_applications (5认同)

小智 5

下面的 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;
}
Run Code Online (Sandbox Code Playgroud)