JS中123456789*987654321运行结果不对

源于leetCode上的这道题
给出两个字符串形式的整数, 返回这两个整数的积

Input:
"123456789"
"987654321"
Output:
"121932631112635260"
Expected:
"121932631112635269"

在console里算了下, 的确不对

clipboard.png

最后一位明明应该是9的嘛.

可能是什么原因造成的呢? 看了下结果的长度是18位, 貌似没有超出表示范围啊?
这种情况又有何解决方案呢?

阅读 6k
6 个回答

JavaScript 最大的数 Number.MAX_SAFE_INTEGER

很明显这种题是大数运算,题目的提示也说了:

Converting the input string to integer is NOT allowed.
不允许将输入字符串直接转换为数字。

给你写个简单的大数乘法:

var multiply = function(x, y) {
    if(x === "0" || y === "0") {
        return("0");
    }
    const ans = [],
        num1 = x.split("").map((n) => parseInt(n)).reverse(),
        num2 = y.split("").map((n) => parseInt(n)).reverse();

    for(let i = 0; i < num1.length; i++) {
        for(let j = 0; j < num2.length; j++) {
            if(ans[i + j] === undefined) {
                ans[i + j] = 0;
            }
            ans[i + j] += num1[i] * num2[j];
            if(ans[i + j] > 9) {
                if(ans[i + j + 1] === undefined) {
                    ans[i + j + 1] = 0;
                }
                ans[i + j + 1] += parseInt(ans[i + j] / 10);
                ans[i + j] %= 10;
            }
        }
    }

    return(ans.reverse().join(""));
};

大数运算,好像leetcode上还有一道题是大数加法的:
图片描述

function multiply(num1, num2) {
    let m = num1.length,
        n = num2.length;
    let pos = Array.from({length: m + n}).fill(0);
    for (let i = m - 1; i >= 0; i--) {
        for (let j = n - 1; j >= 0; j--) {
            let mul = num1[i] * num2[j];
            let p1 = i + j,
                p2 = i + j + 1,
                sum = mul + pos[p2];
            pos[p1] += sum / 10 >>> 0;
            pos[p2] = sum % 10;
        }
    }
    return pos.join('');
}

console.log(multiply("123456789", "987654321"))

JavaScript没有整数,只有Number,Number其实是浮点数。Number有一个MAX_SAFE_INTEGER,超出这个范围的数有可能会出现问题。
我在Chrome的console中测试了一下:

var a = 9007199254740993
console.log(a) // 输出:9007199254740992

浮点数范围:

as  large  as ±1.7976931348623157 × 10的308次方
as small as ±5 × 10的−324次方

精确整数范围:

The JavaScript number format allows you to exactly represent all integers between
−9007199254740992  and 9007199254740992 (即正负2的53次方)

数组索引还有位操作:

正负2的31次方

你的运算超出了精确范围!

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题