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

  • 相关阅读:
    PHP常用时间函数总结
    LNMP 1.2缓存加速类扩展(xcache/Redis/memcached/eAccelerator)、imageMagick、ionCube安装教程
    LNMP强制https访问
    查看lnmp的编译参数和版本
    LNMP 1.2/1.3+升级Nginx、MySQL/MariaDB、PHP教程
    微信小程序websocket多页面冲突解决办法
    lnmp “.user.ini”无法删除解决方法
    一些js函数
    vue下拉框三级联动
    mysql取某个字段中的内容有等于数组中某个元素的数据
  • 原文地址:https://www.cnblogs.com/caoke/p/10843029.html
Copyright © 2011-2022 走看看