js分治算法实现大整数相加,算法复杂度为O(n/15)
js分治算法实现大整数相减,算法复杂度为O(n/15)+比较大小0-n/15;
//从字符截取数字 function getMidNum(str,start,len) { if(start+len>0){ return +str.substr(start<0?0:start,start<0?start+len:len); }else{ return 0; } } //比较两个大整数的大小,返回-1,0,1 function bigNumCompare(a,b) { let back=0; let max=Math.ceil(Math.max(a.length,b.length)/15); //分成多少段,从左边开始 for(let i=max;i>0;i--){ const num1=getMidNum(a,a.length-i*15,15); const num2=getMidNum(b,b.length-i*15,15); //15位数字相减 let cur=num1-num2; if(cur<0){ back=-1; break }else if(cur>0){ back=1; break } } return back; } /*js分治算法实现大整数相加,算法复杂度为O(n/15) * 1、整数的精度是Math.pow(2,53),大于 9007199254740992 的可能会丢失精度,所以相加的字符长度为15位。 * 2、负数+负数、负数+正数、正数+负数的情况 * */ function bigNumAdd(a,b){ if(a[0]==='-'&&b[0]==='-'){ return '-'+bigNumAdd(a.substr(1),b.substr(1)) }else if(a[0]==='-'){ return bigNumSub(b,a.substr(1)) }else if(b[0]==='-'){ return bigNumSub(a,b.substr(1)) } let res=''; let temp=0; let len1=a.length; let len2=b.length; let n=Math.ceil(Math.max(len1,len2)/15); //分成多少段 for(let i=1;i<n+1;i++){ const num1=getMidNum(a,len1-i*15,15); const num2=getMidNum(b,len2-i*15,15); //15位数字相加 let strTemp= String(temp+ num1 + num2); if(i!==n){ //异常1:处理000000000000000+整数的异常情况 if(strTemp.length<15){ strTemp='0'.repeat(15-strTemp.length)+strTemp; res=strTemp+res; temp=0; continue; } //异常2:15位相加等于16位 if(strTemp.length===16){ res=strTemp.substr(1,15)+res; temp=1; continue; } } //相加后的结果放入res前面 res=strTemp+res; temp=0; } return res; } //大整数相减,处理 负数-负数、负数-正数、正数-负数的情况 function bigNumSub(a,b){ if(a[0]==='-'&&b[0]==='-'){ return bigNumSub(b.substr(1),a.substr(1)) }else if(a[0]==='-'){ return '-'+bigNumAdd(a.substr(1),b) }else if(b[0]==='-'){ return bigNumAdd(a,b.substr(1)) } let symb=''; if(bigNumCompare(a,b)<0){ symb='-'; const cache=a; a=b; b=cache; } let res=''; let temp=0; let n=Math.ceil(a.length/15); //分成多少段 for(let i=1;i<n+1;i++){ const num1=getMidNum(a,a.length-i*15,15); const num2=getMidNum(b,b.length-i*15,15); //15位数字相减 let tempNum=num1 - num2-temp; if(tempNum<0){ temp=1; tempNum=1000000000000000+tempNum; }else{ temp=0; } let strTemp= String(tempNum); if(i!==n){ //异常1:处理000000000000000+整数的异常情况 if(strTemp.length<15){ strTemp='0'.repeat(15-strTemp.length)+strTemp; } } //相加后的结果放入res前面 res=strTemp+res; } return symb+res; } //45位 const a='-108900000000000000000000000000000'; const b='-1'; const c='1234567890123456789012345678901234567890'; console.log(bigNumSub(a,b)) // console.log(bigNumAdd(a,a)) // console.log(bigNumAdd(c,b))
测试
const a='-108900000000000000000000000000000';
const b='-1';
const c='-1234567890123456789012345678901234567890';
console.log(bigNumSub(a,b))
console.log(bigNumAdd(a,a))
console.log(bigNumAdd(c,b))
输出结果:
-108899999999999999999999999999999
-217800000000000000000000000000000
-1234567890123456789012345678901234567891
Process finished with exit code 0