如何实现两个大数相乘
思路:开始有点懵,之前做过两个数相加,但是还真没遇到到相乘的情况, 顺着相加的思路做。 采用模拟竖式的方式写算法
- 常规乘法是,第二个数的从后往前每个数和第一个数从后往前相乘,然后取模放到对应位置,如果有进位,下次乘完再加上上次的进位
- 第二个数二位乘完之后的结果正好比上一个结果要向前错一位,依此类推
- 将每次乘完的结果相加,这里就转换成了多个大数相加,此时可以乘完一轮就加,就变成两数相加了
算法实现
1. 对字符串分割,便于遍历
由于两个数量可能不等,所以要取两个数最大的位数,不满足的需要补充0,以便遍历的时候位数可以对齐,相关代码如下
js
const max = Math.max(num1.length, num2.length);
const arr1 = `${num1}`.padStart(max, "0").split("");
const arr2 = `${num2}`.padStart(max, "0").split("");2. 模拟相乘,循环两个数的位数,双层循环,遍历所有位
js
for (let i = arr1.length - 1; i >= 0; i--) {
const oneResult = [];//存放每一轮的计算结果
pre = 0;
for (let k = arr2.length - 1; k >= 0; k--) {
let total = ~~arr1[i] * ~~arr2[k] + ~~pre;//这里要加上上一轮的进位pre
const mod = total % 10;
pre = ~~(total / 10);
oneResult.unshift(mod);//放到计算结果里,从前面插入
if (k == 0 && pre) {//考虑到最后可能还是有进位,所以最后一次遍历如果还有进位则需要把进位插入到最前面
oneResult.unshift(pre)
}
}
// ...略
}3. 下一次循环要向前错一位
所以错过之后,后面的位数要补0
因为循环是从后往前循环,所以索引是递减,但是错位的0是递增,所以补0的索引要用当前总索引数减去当前循环的索引值,得到需要补充0的个数,然后遍历补充0
js
let j = arr1.length - 1 - i;
while (j != 0) {
oneResult.push("0"); //尾部补0 为了错位叠加
j--;
}4. 将上一次得到的结果和本轮结果叠加,得到最终结果
js
result = add(result.join(""), oneResult.join("")).split("");叠加的算法就是两数之和了,是另外一个题 了
两数之和与两数之积不同的是,只有一次循环
两数之和算法如下:
js
const add = (num1, num2) => {
const max = Math.max(num1.length, num2.length);
const arr1 = `${num1}`.padStart(max, "0").split("");
const arr2 = `${num2}`.padStart(max, "0").split("");
const result = [];
let pre = 0;//每次循环之后一定要重制一下进位
for (let i = arr1.length - 1; i >= 0; i--) {
const total = ~~arr1[i] + ~~arr2[i] + ~~pre;
const mod = total % 10;
pre = ~~(total / 10);
result[i] = mod;
}
if (pre) {
result.unshift(pre);
}
//去除前缀0
for (let i = 0; i < result.length; i++) {
if (~~result[i] == 0) {
result.shift();
i--;
} else {
break;
}
}
return result.join("");
};待改进
算法效率不高,比较耗时