js分治算法实现大整数相加、相减

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

posted @ 2019-05-10 10:34  无工时代  阅读(1296)  评论(0编辑  收藏  举报