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 相关文章推荐
JavaScript的Function详细
Nov 14 Javascript
jquery中交替点击事件toggle方法的使用示例
Dec 08 Javascript
js模拟hashtable的简单实例
Mar 06 Javascript
js中直接声明一个对象的方法
Aug 10 Javascript
jQuery实现仿Alipay支付宝首页全屏焦点图切换特效
May 04 Javascript
javascript为按钮注册回车事件(设置默认按钮)的方法
May 09 Javascript
谈谈我对JavaScript DOM事件的理解
Dec 18 Javascript
DWR中各种java方法的调用
May 04 Javascript
使用store来优化React组件的方法
Oct 23 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
Apr 08 Javascript
基于小程序请求接口wx.request封装的类axios请求
Jul 02 Javascript
如何实现vue的tree组件
Dec 03 Vue.js
详解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
什么是短波收听SWL
2021/03/01 无线电
php数组函数序列之prev() - 移动数组内部指针到上一个元素的位置,并返回该元素值
2011/10/31 PHP
PHP实现的比较完善的购物车类
2014/12/02 PHP
PHP生成随机数的方法总结
2018/03/01 PHP
含有CKEditor的表单如何提交
2014/01/09 Javascript
AngularJS入门知识之MVW类框架的编程思想探讨
2014/12/08 Javascript
js判断子窗体是否关闭的方法
2015/08/11 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
2016/02/25 Javascript
图文详解Heap Sort堆排序算法及JavaScript的代码实现
2016/05/04 Javascript
使用jQuery制作遮罩层弹出效果的极简实例分享
2016/05/12 Javascript
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
2017/06/13 Javascript
bootstrap响应式工具使用详解
2017/11/29 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
2018/05/05 Javascript
AngularJS中ng-options实现下拉列表的数据绑定方法
2018/08/13 Javascript
js前端面试之同步与异步问题详解
2019/04/03 Javascript
vue router 通过路由来实现切换头部标题功能
2019/04/24 Javascript
从Node.js事件触发器到Vue自定义事件的深入讲解
2020/06/26 Javascript
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
python通过getopt模块如何获取执行的命令参数详解
2017/12/29 Python
详解python中的线程与线程池
2019/05/10 Python
Python寻找路径和查找文件路径的示例
2019/07/10 Python
pytorch之添加BN的实现
2020/01/06 Python
HTML5 Canvas实现烟花绽放特效
2016/03/02 HTML / CSS
HTML5 新表单类型示例代码
2018/03/20 HTML / CSS
英国儿童图书网站:Scholastic
2017/03/26 全球购物
波兰数码相机及配件网上商店: Cyfrowe.pl
2017/06/19 全球购物
PyQt 如何创建自定义QWidget
2021/03/24 Python
创业计划书的主要内容有哪些
2014/01/29 职场文书
违反校纪校规检讨书
2014/02/15 职场文书
酒店爱岗敬业演讲稿
2014/09/02 职场文书
医院志愿者活动总结
2015/05/06 职场文书
爱护环境建议书
2015/09/14 职场文书
MySQL学习总结-基础架构概述
2021/04/05 MySQL
Python安装及建立虚拟环境的完整步骤
2022/06/25 Servers
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
2022/08/05 数码科技