JavaScript实现大数相乘

282 阅读3分钟

「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。

说在前面

平时我们做计算的时候只需要将需要计算的式子输入给计算机,计算机就会返回其计算结果给我们,但不知道你们有没有发现,在式子中的数字过大时,返回的结果和我们想象中的结果就会变得不一样,就像下面这个式子一样: 1111111111 * 1111111111 在浏览器控制台的计算结果为:1234567900987654400

image.png 我们可以很容易看出这个结果并不对,个位数不可能为零,那么正确的计算结果应该为什么呢?让我们拿起草稿纸计算一下,得出结果为:1234567900987654321

出错原因

其实这是计算机计算精度的问题,并非计算错误。 理论上,计算机可以运行15位正整数或小数点后15位小数的计算,当结果超出上述数值时就会出现这样的错误结果。 所以,可以计算的数值(包含结果数值)最大位999999999999998;最小为:0.999999999999998。

解决方案

1、更换计算机

可以使用更高精度的计算机来进行计算

2、手动计算

我们也可以直接拿出纸笔来进行计算,接受过九年义务教育的同学还是计算出结果的

3、字符串相乘算法

当然最方便的是写一个字符串相乘的算法让计算机来帮我们计算

字符串相乘算法

在leetcode上有一道类似的题目,有兴趣的同学可以先自己去尝试一下。

题目链接

43. 字符串相乘

题目描述

给定两个以字符串形式表示的非负整数 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('');
};