JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
作者:十方魔 发布时间:2024-05-05 09:13:21
本文实例讲述了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程序设计有所帮助。
来源:https://blog.csdn.net/github_36487770/article/details/77446598
猜你喜欢
- 本文以Python3.8为例1、 compileall py文件转换为pyc1.1、compileall命令行模式不需要额外安装,pytho
- 最近在做文章页盖楼显示的项目,数据来源是跟贴系统生成的UTF8格式的JSON数据。文章页的HTML编码格式是GB2312,在javascri
- 1. 数组数组是 Golang 中的一种基本数据类型,用于存储固定数量的同类型元素。在 Golang 中,数组的长度是固定的,并且必须在定义
- 在JavaScript中,数组本质上是一种特殊的对象,它的类型值会返回 object。如果我们需要比较两个数组是否相等,不能像比较基本类型(
- 【错误原因】:mysql_query执行超时.【解决办法】:修改php.ini中的 max_execution_time的值,默认为300,
- 下拉菜单在实际生活中也挺常见的,它实现的js代码与tab选卡,手风琴几乎一样,在此不过多赘述。我仿照苏宁易购官网写了一个下拉菜单,实现代码如
- 大家在开发Python的过程中,一定会遇到很多反斜杠的问题,很多人被反斜杠的数量搞得头大。首先我们写一段非常简单的Python代码,它的作用
- 养成良好的编码习惯,一个合格的程序员需要掌握一些编写单元测试的能力。单元测试也可以整体上提升我们的代码质量,这里介绍下 VUE 组件的单元测
- 因工作需要研究了支付宝即时到帐接口,并成功应用到网站上,把过程拿出来分享。即时到帐只是支付宝众多商家服务中的一个,表示客户付款,客户用支付宝
- jsp表达式方式: <center> <table border="1"> <% for
- 本文实例讲述了jQuery实现的简单分页。分享给大家供大家参考,具体如下:<!DOCTYPE html PUBLIC "-/
- 1. 在 Python 中 XML 文件的编码问题1.Python 使用的xml.etree.ElementTree库只支持解析和生成标准的
- 引言:本人从小白自学python,为了测试基础学习效果,增加一定的促进,想通过参加全国计算机等级考试二级python来检验基础学习情况。在学
- 前言本文主要跟大家分享了关于Ubuntu 18.04配置mysql及配置远程连接的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看
- 一、需求分析我们首先有一个成绩表单,但是学生的成绩是按照学号进行排序的,现在,我们希望清晰明了的知道每一个学生的名次,并且需要将学生按照成绩
- 上篇更新到pygame实现俄罗斯方块游戏(AI篇2) ,原本应该继续做优化,不过考虑到完成游戏完整性,这张就先把对战做好。一、对战的方块管理
- 目录一、MySQL主从搭建操作步骤二、Django实现读写分离自动指定一、MySQL主从搭建主从配置原理:主库写日志到 BinLog从库开个
- 任务识别用相机拍下来的答题卡,并判断最终得分(假设正确答案是B, E, A, D, B)主要步骤轮廓识别——答题卡边缘识别透视变换——提取答
- 前言之前用vue+ant-design-vue写了一个动态路由的页面,更新看一下不能用了555~~~之前用的组件版本不知道了,回退也不知道哪
- 当我们提到一门编程语言的效率时:通常有两层意思,第一是开发效率,这是对程序员而言,完成编码所需要的时间;另一个是运行效率,这是对计算机而言,