zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    8款最新CSS3表单 环形表单很酷
    8款给力HTML5/CSS3应用插件 可爱的HTML5笑脸
    分享10款效果惊艳的HTML5图片特效
    9款极具创意的HTML5/CSS3进度条动画
    分享9款最新超酷HTML5/CSS3应用插件
    7款HTML5精美应用教程 让你立即爱上HTML5
    (转)整理 node-sass 安装失败的原因及解决办法
    分析Vue框架源码心得
    Vue中的render函数随笔
    微信小程序商业级实战
  • 原文地址:https://www.cnblogs.com/caoke/p/10843029.html
Copyright © 2011-2022 走看看