最大公約數和最小公倍數求解,常用的方法是短除法進行因式分解,然後最大公約數是所有公共因子的乘積,最小公倍數是所有因子的乘積。
本質上求最小公倍數就是求最大公倍數:x=ma, y=mb;m是最大公約數,那最小公倍數就是mab。所以可以得到最大公約數與最小公倍數的關係:
LCM(A,B)×GCD(A,B)=A×B
其中LCM是最小公倍數,GCD是最大公約數
來源:https://blog.csdn.net/Holmofy/article/details/76401074
作者總結出來的結論非常的有用,我們後續就根據這個思路去寫算法。
輾轉相除法(歐幾里得算法)求最大公約數
輾轉相除法:輾轉相除法, 又名歐幾里德算法(Euclidean algorithm),是求最大公約數的一種方法。它的具體做法是:用較大數除以較小數,除數去除出現的餘數(第一餘數),再用第一餘數去除出現的餘數(第二餘數),如此反覆,直到最後餘數是0爲止。如果是求兩個數的最大公約數,那麼最後的除數就是這兩個數的最大公約數。
來源:https://baike.baidu.com/item/輾轉相除法/4625352?fr=aladdin
注:百度百科裏面的描述好像不對。大家可以比較下
具體算法如下:
int max_gcd(int a,int b){
if (a <= 0 || b <= 0) {
printf("please > 0\n");
return -1;
}
if (a<b) {
int tmp = a;
a= b;
b = tmp;
}
int r;
while (a%b > 0) {
r = a%b;
a = b;
b = r;
}
return b;
}
結合文章開頭對於公約數的概念,我這邊還有另外的一種方案去實現,具體代碼如下:
int max_gcd1(int a,int b){
if (a <= 0 || b <= 0) {
printf("please > 0\n");
return -1;
}
if (a<b) {
int tmp = a;
a= b;
b = tmp;
}
int max = 1;
for (int i = 1; i<=b; i++) {
if (b%i == 0 && a%i == 0) {
int tmpMax = max * i;
if (tmpMax <= b) {
if (b%tmpMax == 0 && a%tmpMax == 0){
max = tmpMax;
i = tmpMax;
}else{
max = i;
}
}else{
max = i;
}
}
}
return max;
}
大家可以清晰的感覺到無論是從運算的速度,以及邏輯的清晰度來說,輾轉相除法都有非常大的優勢。
在網上搜了一下,發現我國古代數學家提出了一個更相減損法的算法去求最大公約數。描述如下:
第一步:任意給定兩個正整數;判斷它們是否都是偶數。若是,則用2約簡;若不是則執行第二步。
第二步:以較大的數減較小的數,接着把所得的差與較小的數比較,並以大數減小數。繼續這個操作,直到所得的減數和差相等爲止。
則第一步中約掉的若干個2與第二步中等數的乘積就是所求的最大公約數。
根據描述,我這邊實現如下:
int max_gcd2(int a,int b){
int c = 1;
while (a%2 == 0 && b%2 == 0) {
c *= 2;
a = a/2;
b = b/2;
}
while (a != b) {
if (a > b) {
a = a - b;
}else{
b = b - a;
}
}
return a * c;
}
兩種算法的區別
(1)兩者都是求最大公因數的方法,計算上輾轉相除法以除法爲主,更相減損術以減法爲主,計算次數上輾轉相除法計算次數相對較少,特別當兩個數字大小區別較大時計算次數的區別較明顯。
(2)從結果體現形式來看,輾轉相除法體現結果是以相除餘數爲0則得到,而更相減損術則以減數與差相等而得到。
轉載地址:https://blog.csdn.net/Holmofy/article/details/76401074
更多優質文章,可以微信掃碼關注: