JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】


Posted in Javascript onMay 07, 2018

本文实例讲述了JavaScript求一组数的最小公倍数和最大公约数常用算法。分享给大家供大家参考,具体如下:

方法来自求多个数最小公倍数的一种变换算法(详见附录说明)

最小公倍数的算法由最大公约数转化而来。最大公约数可通过如下步骤求得:

(1) 找到a1,a2,..,an中的最小非零项aj,若有多个最小非零项则任取一个
(2) aj以外的所有其他非0项ak用ak mod aj代替;若没有除aj以外的其他非0项,则转到(4)
(3) 转到(1)
(4) a1,a2,..,an的最大公约数为aj

写了两个版本的javascript求公倍数和公约数,主要偏重于算法,没有太注意命名,很多就直接写的单字母名称。

0. 简单易懂的循环

function getMin(arr){
  var min = Infinity
  arr.forEach(function(item){
    if( item < min && item !=0 ){
      min = item
    }
  })
  return min
}
function howMuchZero(arr){
  var zerocount = 0
  arr.forEach( function(item){
    item === 0 ?
    zerocount++ : zerocount
  }
    )
  if(zerocount === arr.length -1) {
    return true
  }
  else return false
}
function maxDivi(arr){
  do {
  var min = getMin(arr)
  arr = arr.map((item)=> item===min? item:item%min
    )
  }
  while (!howMuchZero(arr))
  return getMin(arr)
}
function minMulti(arr){
  var totalMulti = arr.reduce((pre,item)=>
    pre = pre * item
    )
  var brr = arr.map((item)=>
    totalMulti/item
    )
  var brr_maxDivi = maxDivi(brr)
  return totalMulti/brr_maxDivi
}

1. function套function

var arr_minMulti, arr_maxdivi
function minMulti(arr){
  var totalmulti =
    arr.reduce((multi,curvalue) => multi * curvalue)
  if (totalmulti === 0) {
    arr_minMulti = 0
    return
  }
  var marr = arr.map((item) => totalmulti/item)
  maxDivisor(marr)
   arr_minMulti = totalmulti / arr_maxdivi
}
function maxDivisor(arr){
  var min = getMin(arr)
  if(min === Infinity) {
    arr_maxdivi = min
    return
  }
  var exparr = arr.filter(function(item){
      return (item !== min && item !== 0)
  })
  if(exparr.length === 0){
    arr_maxdivi = min
    return;
  }
  else{
    var modearr = arr.map(function(item){
      return (item === min||item===0)? item:item%min
    })
    console.log(modearr,'modearr')
    maxDivisor(modearr)
  }
}
function getMin(arr){
  var min = Infinity
  arr.forEach(function(item){
    if (item && item < min) {
      min = item
    }
  })
  return min
}
arr =[13,20,10,26]
minMulti(arr)
console.log('最小公倍数',arr_minMulti)

2. object oriented 面向对象

function maxDivisor(arr,origin){
  this.arr = arr
  this.min = this._getMin(arr)
  this.maxDivisor = this._getMaxDiv()
  if(origin){
    this.minMulti = this._getMinMulti()
  }
}
maxDivisor.prototype._getMin = function(arr) {
  var min = Infinity
  arr.forEach(item => min = (item && item < min)? item : min)
  return min
}
maxDivisor.prototype._getMaxDiv = function() {
  var arr_maxdivi
  var self = this,
    arr = this.arr
  function maxDivisor(arr){
    //console.log(self._getMin)
    var min = self._getMin.call(null,arr)
     console.log(min,'min')
    if(min === Infinity) {
      arr_maxdivi = 0
      return ;
    }
    var exparr = arr.filter( item => (item !== min && item != 0) )
    if(exparr.length === 0){
      arr_maxdivi = min
      return;
    }
    else{
      var modearr = arr.map(item =>
        (item === min || item === 0)? item : item % min
      )
      maxDivisor(modearr)
      }
  }
  maxDivisor(this.arr)
  return arr_maxdivi
}
maxDivisor.prototype._getMinMulti = function(){
  var arr = this.arr,
    arr_minMulti
  var totalmulti =
    arr.reduce((multi,curvalue) => multi * curvalue)
  if (totalmulti === 0) {
    return 0
  }
  else {
    var marr = arr.map((item) => totalmulti/item),
    b = new maxDivisor(marr,false)
    arr_minMulti = totalmulti / b.maxDivisor
    return arr_minMulti
  }
}
var a = new maxDivisor([12,9,6],true)
console.log(a)

附录:求多个数最小公倍数的一种变换算法原理分析

令[a1,a2,..,an] 表示a1,a2,..,an的最小公倍数,(a1,a2,..,an)表示a1,a2,..,an的最大公约数,其中a1,a2,..,an为非负整数。对于两个数a,b,有[a,b]=ab/(a,b),因此两个数最小公倍数可以用其最大公约数计算。但对于多个数,并没有[a1,a2,..,an]=M/(a1,a2,..,an)成立,M为a1,a2,..,an的乘积。例如:[2,3,4]并不等于24/(2,3,4)。即两个数的最大公约数和最小公倍数之间的关系不能简单扩展为n个数的情况。

这里对多个数最小公倍数和多个数最大公约数之间的关系进行了探讨。将两个数最大公约数和最小公倍数之间的关系扩展到n个数的情况。在此基础上,利用求n个数最大公约数的向量变换算法计算多个数的最小公倍数。

1.多个数最小公倍数和多个数最大公约数之间的关系

令p为a1,a2,..,an中一个或多个数的素因子,a1,a2,..,an关于p的次数分别为r1,r2,..,rn,在r1,r2,..,rn中最大值为rc1=rc2=..=rcm=rmax,最小值为rd1=rd2=..=rdt=rmin,即r1,r2,..,rn中有m个数所含p的次数为最大值,有t个数所含p的次数为最小值。例如:4,12,16中关于素因子2的次数分别为2,2,4,有1个数所含2的次数为最大值,有2个数所含2的次数为最小值;关于素因子3的次数分别为0,1,0,有1个数所含3的次数为最大值,有2个数所含3的次数为最小值。

对最大公约数有,只包含a1,a2,..,an中含有的素因子,且每个素因子次数为a1,a2,..,an中该素因子的最低次数,最低次数为0表示不包含[1]。

对最小公倍数有,只包含a1,a2,..,an中含有的素因子,且每个素因子次数为a1,a2,..,an中该素因子的最高次数[1]。

定理1:[a1,a2,..,an]=M/(M/a1,M/a2,..,M/an),其中M为a1,a2,..,an的乘积,a1,a2,..,an为正整数。

例如:对于4,6,8,10,有[4,6,8,10]=120,而M=4*6*8*10=1920,M/(M/a1,M/a2,..,M/an) =1920/(6*8*10,4*8*10,4*6*10,4*6*8)=1920/16=120。

证明:

M/a1,M/a2,..,M/an中p的次数都大于等于r1+r2+..+rn-rmax,且有p的次数等于r1+r2+..+rn-rmax的。这是因为

(1)M/ai中p的次数为r1+r2+..+rn-ri,因而M/a1,M/a2,..,M/an中p的次数最小为r1+r2+..+rn-rmax。

(2)对于a1,a2,..,an中p的次数最大的项aj(1项或多项),M/aj中p的次数为r1+r2+..+rn-rmax。

或者对于a1,a2,..,an中p的次数最大的项aj,M/aj中p的次数小于等于M/ak,其中ak为a1,a2,..,an中除aj外其他的n-1个项之一,而M/aj中p的次数为r1+r2+..+rn-rmax。

因此,(M/a1,M/a2,..,M/an)中p的次数为r1+r2+..+rn-rmax,从而M/(M/a1,M/a2,..,M/an)中p的次数为rmax。

上述的p并没有做任何限制。由于a1,a2,..,an中包含的所有素因子在M/(M/a1,M/a2,..,M/an)中都为a1,a2,..,an中的最高次数,故有[a1,a2,..,an]=M/(M/a1,M/a2,..,M/an)成立。

得证。

定理1对于2个数的情况为[a,b]=ab/(ab/a,ab/b)=ab/(b,a)=ab/(a,b),即[a,b]=ab/(a,b)。因此,定理1为2个数最小公倍数公式[a,b]=ab/(a,b)的扩展。利用定理1能够把求多个数的最小公倍数转化为求多个数的最大公约数。

2.多个数最大公约数的算法实现

根据定理1,求多个数最小公倍数可以转化为求多个数的最大公约数。求多个数的最大公约数(a1,a2,..,an)的传统方法是多次求两个数的最大公约数,即

(1)用辗转相除法[2]计算a1和a2的最大公约数(a1,a2)

(2)用辗转相除法计算(a1,a2)和a3的最大公约数,求得(a1,a2,a3)

(3)用辗转相除法计算(a1,a2,a3)和a4的最大公约数,求得(a1,a2,a3,a4)

(4)依此重复,直到求得(a1,a2,..,an)

上述方法需要n-1次辗转相除运算。

本文将两个数的辗转相除法扩展为n个数的辗转相除法,即用一次n个数的辗转相除法计算n个数的最大公约数,基本方法是采用反复用最小数模其它数的方法进行计算,依据是下面的定理2。

定理2:多个非负整数a1,a2,..,an,若aj>ai,i不等于j,则在a1,a2,..,an中用aj-ai替换aj,其最大公约数不变,即 (a1,a2,..,aj-1,aj,aj+1,..an)=(a1,a2,..,aj-1,aj-ai,aj+1,..an)。

例如:(34,24,56,68)=(34,24,56-34,68)=(34,24,22,68)。

证明:

根据最大公约数的交换律和结合率,有

(a1,a2,..,aj-1,aj,aj+1,..an)= ((ai,aj),(a1,a2,..,ai-1,ai+1,..aj-1,aj+1,..an))(i>j情况),或者

(a1,a2,..,aj-1,aj,aj+1,..an)= ((ai,aj),(a1,a2,..,aj-1,aj+1,..ai-1,ai+1,..an))(i<j情况)。

而对(a1,a2,..,aj-1,aj-ai,aj+1,..an),有

(a1,a2,..,aj-1,aj-ai,aj+1,..an)= ((ai, aj-ai),( a1,a2,..,ai-1,ai+1,.. aj-1,aj+1,..an))(i>j情况),或者

(a1,a2,..,aj-1,aj-ai,aj+1,..an)= ((ai, aj-ai),( a1,a2,..,aj-1,aj+1,.. ai-1,ai+1,..an))(i<j情况)。

因此只需证明(ai,aj)=( ai, aj-ai)即可。

由于(aj-ai)= aj-ai,因此ai,aj的任意公因子必然也是(aj-ai)的因子,即也是ai,( aj-ai)的公因子。由于aj = (aj-ai)+ai,因此ai,( aj-ai)的任意公因子必然也是aj的因子,即也是ai,aj的公因子。所以,ai,aj的最大公约数和ai,(aj-ai) 的最大公约数必须相等,即(ai,aj)=(ai,aj-ai)成立。

得证。

定理2类似于矩阵的初等变换,即

令一个向量的最大公约数为该向量各个分量的最大公约数。对于向量<a1,a2,..,an>进行变换:在一个分量中减去另一个分量,新向量和原向量的最大公约数相等。

求多个数的最大公约数采用反复用最小数模其它数的方法,即对其他数用最小数多次去减,直到剩下比最小数更小的余数。令n个正整数为a1,a2,..,an,求多个数最大共约数的算法描述为:

(1)找到a1,a2,..,an中的最小非零项aj,若有多个最小非零项则任取一个

(2)aj以外的所有其他非0项ak用ak mod aj代替;若没有除aj以外的其他非0项,则转到(4)

(3)转到(3)

(4)a1,a2,..,an的最大公约数为aj

例如:对于5个数34, 56, 78, 24, 85,有

(34, 56, 78, 24, 85)=(10,8,6,24,13)=(4,2,6,0,1)=(0,0,0,0,1)=1,

对于6个数12, 24, 30, 32, 36, 42,有

(12, 24, 30, 32, 36, 42)=(12,0,6,8,0,6)=(0,0,0,2,0,6)=(0,0,0,2,0,0)=2。

3. 多个数最小共倍数的算法实现

求多个数最小共倍数的算法为:

(1)计算m=a1*a2*..*an

(2)把a1,a2,..,an中的所有项ai用m/ai代换

(3)找到a1,a2,..,an中的最小非零项aj,若有多个最小非零项则任取一个

(4)aj以外的所有其他非0项ak用ak mod aj代替;若没有除aj以外的其他非0项,则转到(6)

(5)转到(3)

(6)最小公倍数为m/aj

上述算法在VC环境下用高级语言进行了编程实现,通过多组求5个随机数最小公倍数的实例,与标准方法进行了比较,验证了其正确性。标准计算方法为:求5个随机数最小公倍数通过求4次两个数的最小公倍数获得,而两个数的最小公倍数通过求两个数的最大公约数获得。

5. 结论

计算多个数的最小公倍数是常见的基本运算。n个数的最小公倍数可以表示成另外n个数的最大公约数,因而可以通过求多个数的最大公约数计算。求多个数最大公约数可采用向量转换算法一次性求得。

Javascript 相关文章推荐
推荐20家国外的脚本下载网站
Apr 28 Javascript
javascript禁用键盘功能键让右击及其他键无效
Oct 09 Javascript
Javascript单元测试框架QUnitjs详细介绍
May 08 Javascript
jquery实现动态改变div宽度和高度
May 08 Javascript
javascript实现动态改变层大小的方法
May 14 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
Sep 01 Javascript
深入剖析JavaScript面向对象编程
Jul 12 Javascript
jquery-mobile基础属性与用法详解
Nov 23 Javascript
Javascript封装id、class与元素选择器方法示例
Mar 13 Javascript
Vue进度条progressbar组件功能
Apr 17 Javascript
Vue3.0的优化总结
Oct 16 Javascript
antd table按表格里的日期去排序操作
Nov 17 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
May 07 #Javascript
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
May 07 #Javascript
Vue 实现树形视图数据功能
May 07 #Javascript
JavaScript 跨域之POST实现方法
May 07 #Javascript
ES6关于Promise的用法详解
May 07 #Javascript
React Form组件的实现封装杂谈
May 07 #Javascript
vue如何将v-for中的表格导出来
May 07 #Javascript
You might like
为了这两部电子管收音机,买了6套全新电子管和10粒刻度盘灯泡
2021/03/02 无线电
php制作unicode解码工具(unicode编码转换器)代码分享
2013/12/24 PHP
深入解读php中关于抽象(abstract)类和抽象方法的问题分析
2014/01/03 PHP
yum命令安装php7和相关扩展
2016/07/04 PHP
CI框架常用函数封装实例
2016/11/21 PHP
php调用云片网接口发送短信的实现方法
2017/10/25 PHP
浏览器无法运行JAVA脚本的解决方法
2008/01/09 Javascript
js函数名与form表单元素同名冲突的问题
2014/03/07 Javascript
js style动态设置table高度
2014/10/21 Javascript
javascript自动生成包含数字与字符的随机字符串
2015/02/09 Javascript
js数组依据下标删除元素
2015/04/14 Javascript
js实现头像图片切割缩放及无刷新上传图片的方法
2015/07/17 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
js实现年月日表单三级联动
2020/04/17 Javascript
Bootstrap超大屏幕的实现代码
2017/03/22 Javascript
配置nodejs环境的方法
2017/05/13 NodeJs
vue弹窗消息组件的使用方法
2020/09/24 Javascript
Vue项目中使用Vux的安装过程
2018/05/01 Javascript
clipboard.js在移动端复制失败的解决方法
2018/06/13 Javascript
vue和webpack安装命令详解
2018/06/15 Javascript
使用 Vue 实现一个虚拟列表的方法
2019/08/20 Javascript
浅析JavaScript 函数柯里化
2020/09/08 Javascript
Python 操作文件的基本方法总结
2017/08/10 Python
python opencv检测目标颜色的实例讲解
2018/04/02 Python
Python批量发送post请求的实现代码
2018/05/05 Python
python安装twisted的问题解析
2018/08/21 Python
PyCharm2020.1.1与Python3.7.7的安装教程图文详解
2020/08/07 Python
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
html5适合移动应用开发的12大特性
2014/03/19 HTML / CSS
英国潮流网站:END.(全球免邮)
2017/01/16 全球购物
GWT (Google Web Toolkit)有哪些主要的原件组成?
2015/06/08 面试题
孝老爱亲模范事迹材料
2014/05/25 职场文书
现役军人家属慰问信
2015/03/24 职场文书
党员干部廉洁自律承诺书
2015/04/28 职场文书
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技