js从0开始实现大整数加法

6 篇文章 0 订阅

如果两个整数太大,超过了 2^52 - 1 的时候,做加法时,会出现精度损失的现象,这时候可以直接利用js提供bigInt类型来做加法,这里就不再赘述了。我这里是用字符串来输出做加法的结果,通过拆分数字来实现无精度损失的加法运算。具体实现如下:


function sum(a, b, step = 9){
    const ar1 = splitNumber(a, step)
    const ar2 = splitNumber(b, step)
    
    if (ar1[0] !== ar2[0]) {
        if (ar1[0] === '-') return minus(ar2, ar1, step)
        else return minus(ar1, ar2)
    }
    if (ar1[0] === '-') return '-' + plus(ar1, ar2, step)
    return plus(ar1, ar2, step)
    
}
/**
* 做加法,需要注意的是,若是拆分后的字符串以0开头需要在计算结果后补上去
**/
function plus(ar1, ar2, step){
    let sum = []
    const factor = Math.pow(10, step)
    let len1 = ar1.length
    let len2 = ar2.length
    let len = len1
    if (len2 < len) len = len2
    
    let overflow = false
    let i = 1
    for(i = 1; i< len; i++) {
        let rs = parseInt(ar1[i],10) + parseInt(ar2[i],10)
        if (overflow) rs++
        overflow = rs >= factor
        let startsWith0 = false
        if (!overflow && (ar1[i].startsWith('0') || ar2[i].startsWith('0'))) {
            startsWith0 = true
            rs += factor
        }
        if (overflow || startsWith0) {
            sum.push(rs.toString().substr(1))
        } else {
            sum.push(rs.toString())
        }
    }
    let arr
    if (len1 > len2) {
        arr = ar1
        len = len1
    } else if (len2 > len1) {
        arr = ar2
        len = len2
    }
    
    for(let j = i; j < len; j++) {
        let rs = arr[j]
        if (overflow) {
            rs++
        }
        overflow = rs >= factor

        let startsWith0 = false
        if (!overflow && arr[j].startsWith('0')) {
            startsWith0 = true
            rs += factor
        }
         if (overflow || startsWith0) {
            sum.push(rs.toString().substr(1))
        } else {
            sum.push(rs.toString())
        }
    } 
    return sum.reverse().join('')
}

/**
* 做减法。计算的结果需要把数字字符串前面的0去掉
**/
function minus(ar1, ar2, step) {
    let sum = []
    const factor = Math.pow(10, step)
    let len1 = ar1.length
    let len2 = ar2.length
    let len = len1
    if (len2 < len) len = len2
    
    let isNegtive = false
    let big = ar1
    let small = ar2
    if (len1 < len2 || len1 == len2 && ar1[ar1.length - 1] < ar2[ar2.length - 1]) {
        isNegtive = true
        big = ar2
        small = ar1
    } 
    
    let overflow = false
    let i = 1
    for(i = 1; i< len; i++) {
        let rs = parseInt(big[i],10) - parseInt(small[i],10)
        if (overflow) rs--
        overflow = rs < 0
        
        if (overflow) {
            rs += factor
            sum.push(rs.toString().substr(1))
        } else {
            sum.push(rs.toString())
        }
    }
    
    for(let j = i, l = big.length; j < l; j++) {
        let rs = big[j]
        if (overflow) {
            rs--
        }
        overflow = rs < 0
         if (overflow) {
            rs += factor
            sum.push(rs.toString().substr(1))
        } else {
            sum.push(rs.toString())
        }
    } 
    const num = sum.reverse().join('')
    return (isNegtive ? '-' : '') + num.replace(/^0+/, '')
}

/**
* step 表示拆分的最小长度。把很大的数字拆分成长度不超过step的值
* 的数字字符串。数组的第一个元素是符号位,即“+”, “-”
**/
function splitNumber(num, stp){
    let val = num.toString()
    const rs = []
    if (val[0] === '-') {
        rs.push('-')
        val = val.substr(1)
    } else {
        rs.push('+')
    }
    let i = val.length - 1
    let step = stp > 0 ? stp : 9
    while(i>=0) {
        i -= step
        if (i >= 0) {
            rs.push(val.substr(i + 1, step))
        } else {
            rs.push(val.substr(0, step + i + 1))
        } 

    }
    return rs
}

function go() {
   const a = 123857457837657242
   const b = 832842784782784783333
   rs = sum(a, b)
    console.log(rs)
}

go()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值