前言
在超大数相加或相乘的时候,当结果超过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时,如果参数是大数,请先转为字符串。)