算法——最大公约数

百度百科上介绍的最大公约数的求法(限两个数)主要有两种:辗转相除法和更相减损法。

辗转相除法

辗转相除法,百度百科上的示例:

用(a,b)表示a和b的最大公约数。

例如,求(319,377):
∵ 319÷377=0(余319)
∴(319,377)=(377,319);
∵ 377÷319=1(余58)
∴(377,319)=(319,58);
∵ 319÷58=5(余29),
∴ (319,58)=(58,29);
∵ 58÷29=2(余0),
∴ (58,29)= 29;
∴ (319,377)=29.
也就是说,求两个数的最大公约数时,先用较大数除以较小数,如果能整除,最大公约数就等于较小数;否则用较小数除以第一步的余数,如果能整除,最大公约数就等于第一步的余数;否则,用当前获得的余数除以上一步的余数,直到能整除为止。此时作为除数的那个数就是最开始那两个数的最大公约数。
下面是代码:
 1 function gcm(m,n) {
 2    var a, c, e, f;
 3    //对m,n排序,较小的在前,较大的在后
 4    if(m > n) {
 5       a = m;
 6       m = n;
 7       n = a;
 8    }
 9    c = m, e = n, f = c;
10    while(c !== 0) {
11       f = e % c;
12       e = c;
13       c = f;
14    }
15    alert(e);
16    return e;
17 }

代码中主要是while循环那里有点绕。(参考知乎上的答案

更相减损法

百度百科上的解释:

第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
用第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
 
例1、用更相减损术求98与63的最大公约数。
解:由于63不是偶数,把98和63以大数减小数,并辗转相减:
98-63=35
63-35=28
35-28=7
28-7=21
21-7=14
14-7=7
所以,98和63的最大公约数等于7。
 
例2、用更相减损术求260和104的最大公约数。
解:由于260和104均为偶数,首先用2约简得到130和52,再用2约简得到65和26。
此时65是奇数而26不是奇数,故把65和26辗转相减:
65-26=39
39-26=13
26-13=13
所以,260与104的最大公约数等于13乘以第一步中约掉的两个2,即13*2*2=52。
 
下面是代码:
 1 function gcm2(m,n) {
 2    var a, c, e, f, index = 0;
 3    //对m,n排序,较小的在前,较大的在后
 4    if(m > n) {
 5       a = m;
 6       m = n;
 7       n = a;
 8    }
 9    //如果m,n都为偶数
10    while(m % 2 === 0 && n % 2 === 0) {
11       m = m/2;
12       n = n/2;
13       index++;
14    }
15 
16    f = m, e = n, c = n - m;
17    while(c !== f) {
18       e = f;
19       f = c;
20       c = e - f;
21       if(c < 0) {
22          c = -c;
23       }
24    }
25    alert(f*2*index);
26    return f*2*index;
27 }

计算上辗转相除法以除法为主,更相减损法以减法为主。计算次数上辗转相除法计算次数相对较少,特别当两个数字大小区别较大时计算次数的区别较明显。

要求多个数的最大公约数,可以先求出其中任意两个数的最大公约数,再求这个最大公约数与第三个数的最大公约数,依次求下去,直到最后一个数为止。最后所得的那个最大公约数,就是所有这些数的最大公约数。

求多个数的最小公倍数

两个数的最小公倍数等于这两个数的乘积除以这两个数的最大公约数。

求多个数的最小公倍数时,可以先求出其中两个数的最小公倍数,再求这两个数的最小公倍数与第三个数的最小公倍数,以此类推,直到最后一个数为止。最后得到的最小公倍数就是这几个数的最小公倍数。

下面是代码:

 1 function smallestCommons(arr) {
 2   arr = arr.sort(function(a,b) {
 3     return a-b;
 4   });
 5   var brr = [];
 6   for (var i = arr[0]; i <= arr[1]; i++) {
 7      brr.push(i);
 8   }
 9   var m,n,c,e,f;
10   
11   for (var i = 0; i < brr.length; i++) {
12      
13      if(brr[i] <=  brr[i+1]) {
14        m = brr[i];
15        n = brr[i+1];
16      } else {
17        m = brr[i+1];
18        n = brr[i];
19      }
20     
21     
22     //求两个数的最大公约数
23      c = m, e = n, f = c;
24      while(c !== 0) {
25       f = e % c;
26       e = c;
27       c = f;
28      }
29      
30      //求两个数的最小公倍数
31      var d = m * n / e;
32      //alert(d);
33      brr.splice(0,2,d);
34 
35 
36      if(brr.length === 1) {
37       num = d;
38       break;
39      }
40      i = -1;
41   }
42 
43   console.log(num);
44   return num;
45 }

函数smallestCommons()接收一个数组参数,这个数组包含两项,这个函数的作用是找出这两项之间连续数字的最小公倍数,最后返回这个最小公倍数。

比如:

smallestCommons([1, 13]);//返回 360360。

 

posted @ 2016-11-23 11:31  Fogwind  阅读(23366)  评论(0编辑  收藏  举报