「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。
说在前面
平时我们做计算的时候只需要将需要计算的式子输入给计算机,计算机就会返回其计算结果给我们,但不知道你们有没有发现,在式子中的数字过大时,返回的结果和我们想象中的结果就会变得不一样,就像下面这个式子一样: 1111111111 * 1111111111 在浏览器控制台的计算结果为:1234567900987654400
我们可以很容易看出这个结果并不对,个位数不可能为零,那么正确的计算结果应该为什么呢?让我们拿起草稿纸计算一下,得出结果为:1234567900987654321
出错原因
其实这是计算机计算精度的问题,并非计算错误。 理论上,计算机可以运行15位正整数或小数点后15位小数的计算,当结果超出上述数值时就会出现这样的错误结果。 所以,可以计算的数值(包含结果数值)最大位999999999999998;最小为:0.999999999999998。
解决方案
1、更换计算机
可以使用更高精度的计算机来进行计算
2、手动计算
我们也可以直接拿出纸笔来进行计算,接受过九年义务教育的同学还是计算出结果的
3、字符串相乘算法
当然最方便的是写一个字符串相乘的算法让计算机来帮我们计算
字符串相乘算法
在leetcode上有一道类似的题目,有兴趣的同学可以先自己去尝试一下。
题目链接
题目描述
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例
示例1
输入: num1 = "1111111111", num2 = "1111111111"
输出: "1234567900987654321"
示例2
输入: num1 = "11", num2 = "11"
输出: "121"
思路
简单来说就是要模拟一个乘法竖式的运算过程
- 1、将两数字的每一位数一一进行相乘计算
- 2、注意位数对齐及进位计算
代码
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
var multiply = function(num1, num2) {
if(num1 == '0' || num2 == '0') return '0';
var res = [],
flag = 0,
ind = 0;
for(let i = num1.length - 1; i >= 0; i--){
for(let j = num2.length - 1; j >= 0; j--){
let temp = parseInt(num1[i]) * parseInt(num2[j]) + flag;
flag = Math.floor(temp / 10);
if((num2.length - 1 - j + ind) >= res.length) res.push(parseInt(temp) % 10);
else{
if((res[num2.length - 1 - j + ind] + (parseInt(temp) % 10)) > 9) flag++;
res[num2.length - 1 - j + ind] = (res[num2.length - 1 - j + ind] + (parseInt(temp) % 10)) % 10;
}
}
if(flag) res[ind + num2.length] = flag;
flag = 0;
ind++;
}
return res.reverse().join('');
};