实现两个正整大数相加,相乘

796 阅读2分钟

前言


在超大数相加或相乘的时候,当结果超过js所能表达的最大值时,就会以科学计数的方式展现,并且精度会有所误差,例如111111111111111111111+1111111111111111111111得到1.2222222222222222e+21,如果相用正常数字表达,就需要自己实现了。

设计思路


用两个字符串来保存大数,做加法的时候,对应位进行相加并记录进位,加入下一位的计算。做乘法运算时,用短的数,依次去乘长的数,再进行相加。

加法


function plus (a, b) {
    const [aArray, bArray] = getReverseArray(a, b);
    const [longArray, shortArray] = getLongAndShortArray(aArray, bArray);
    let i = 0;
    let sum = '';
    let carry = 0;
    
    //用短的数组去加长数组的对应位置
    while (i < shortArray.length) {
        //对应位置、进值相加后的个位值
        sum += (parseInt(aArray[i]) + parseInt(bArray[i]) + carry) % 10 + '';
        //对应位置相加后的进值
        carry = Math.floor((parseInt(aArray[i]) + parseInt(bArray[i]) + carry) / 10);
        i++;
    }
    //长数剩余位置与进值相加
    while (i < longArray.length) {
        sum = sum + ((parseInt(longArray[i]) + carry) % 10);
        carry = Math.floor((parseInt(longArray[i]) + carry) / 10);
        i++;
    }
    //长数最后一位与进值相加后还有进值,则直接将进值放到末尾;
    if (carry !== 0) {
        sum += carry;
    } 
    //将得到结果倒序回来
    sum = sum.split('').reverse().join('');
    return sum;
}

//将数字字符串转换成数组,并倒序,如123转换成[321]
function getReverseArray(a, b) {
    a = a + '';
    b = b + '';
    const aArray = a.split('').reverse();
    const bArray = b.split('').reverse();
    return [aArray, bArray]
}
//获取长短数组
function getLongAndShortArray(arr1, arr2) { 
    return arr1.length >= arr2.length ? [arr1, arr2] : [arr2, arr1];
}

乘法


先将两数相乘分解一下,如 120 * 12

    120
x    12
 ————
    240
+1200
正如上面看到,乘法最终也是乘数的各个位置乘以被乘数,最终相加。所以我们也先将大数分解,相乘后相加。

function multiply (a, b) {
    const [aArray, bArray] = getReverseArray(a, b);
    const [longArray, shortArray] = getLongAndShortArray(aArray, bArray);
    let i = 0;
    let sum = 0;
    //将短数作为乘数,长数作为被乘数
    while (i < shortArray.length) {
        let j = 0;
        //每轮乘数结果
        let currentSum = 0;
        while (j < longArray.length) {
            const loopSum = parseInt(shortArray[i]) * parseInt(longArray[j]) + calcZero(j);
            //plus方法为上述加法函数;
            currentSum = plus(currentSum, loopSum);
            j++;
        }
        sum = plus(sum, currentSum + calcZero(i));
        i++;
    }
    console.log(sum);
}
//计算是第几位,便加几个0,如123*12,当乘数位1*123时,结果加一位0,得1230
function calcZero(index) {
    let str = '';
    while (index !== 0) {
        str = str + '0';
        index--;
    }
    return str;
}

结语

大数相加这类问题一般只有面试才会碰到,实际项目中几率几乎为0。用来练练手还是不错的。第一次写文章,不足的地方还请指导。
(注:调用plus和multiply时,如果参数是大数,请先转为字符串。)