JavaScript

大整数相加

用字符串模拟竖式加法,处理超出 Number 精度的大正整数求和,常见前端面试手写题。

#algorithm #interview

大整数相加

JavaScript 的 Number 基于 IEEE 754 双精度浮点,安全整数范围是 -(2^53 - 1)2^53 - 1(即 Number.MAX_SAFE_INTEGER)。当两个「大正整数」字符串相加时,不能直接用 +Number() 转换,否则会丢失精度。

这道题的核心思路是:模拟小学竖式加法——从低位到高位逐位相加,维护进位。

思路

  1. 将两个操作数转为字符串(或本来就是字符串)
  2. 从最后一位(个位)向前遍历
  3. 对应位数字相加,再加上进位 carry
  4. 当前位结果 = sum % 10,新进位 = Math.floor(sum / 10)
  5. 遍历结束后若仍有进位,需要补一位
  6. 将结果数组反转(或从高位拼接)得到最终字符串

实现一:数组收集后反转

从字符串末尾双指针向前扫,结果先 push 到数组,最后 reverse().join("")

addBigIntegers

javascript
function addBigIntegers(a, b) {
  const strA = String(a);
  const strB = String(b);
  let i = strA.length - 1;
  let j = strB.length - 1;
  let carry = 0;
  const result = [];

  while (i >= 0 || j >= 0 || carry > 0) {
    const digitA = i >= 0 ? Number(strA[i--]) : 0;
    const digitB = j >= 0 ? Number(strB[j--]) : 0;
    const sum = digitA + digitB + carry;
    result.push(sum % 10);
    carry = Math.floor(sum / 10);
  }

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

注意 while 条件里的 carry > 0:最高位相加后若产生进位(如 999 + 1),循环需要多跑一轮。

实现二:左对齐补零,高位拼接

另一种写法是先去掉前导零、用 padStart 对齐长度,再从右向左遍历,把每位结果拼到字符串前面

addBigIntegers(对齐版)

javascript
function addBigIntegers(a, b) {
  a = String(a).replace(/^0+/, "") || "0";
  b = String(b).replace(/^0+/, "") || "0";
  const lth = Math.max(a.length, b.length);
  a = a.padStart(lth, "0");
  b = b.padStart(lth, "0");
  let carry = 0;
  let result = "";
  for (let i = lth - 1; i >= 0; i--) {
    const sum = Number(a[i]) + Number(b[i]) + carry;
    carry = Math.floor(sum / 10);
    result = String(sum % 10) + result;
  }
  if (carry > 0) result = String(carry) + result;
  return result;
}

相比实现一,这版额外处理了前导零"0123" + "456""579"),对小整数也适用。

测试用例

addBigIntegers("999999999999999999999", "1")
// → "1000000000000000000000"

addBigIntegers("12345678901234567890", "98765432109876543210")
// → "111111111011111111100"

addBigIntegers(123, 456)
// → "579"

addBigIntegers("0123", "456")
// → "579"

复杂度与边界

项目说明
时间复杂度O(max(m, n)),m、n 为两数位数
空间复杂度O(max(m, n)),存放结果
负数本题通常只考大整数;若需支持负数,要先处理符号与绝对值大小比较
小数需先对齐小数点,再分别处理整数与小数部分

延伸:BigInt

现代环境可直接用 BigInt

String(BigInt("999999999999999999999") + BigInt("1"))
// → "1000000000000000000000"

面试手写时仍建议掌握字符串模拟竖式加法——考察的是对进位、边界和字符串操作的理解,而非 API 记忆。

小结

  • 大整数相加不能依赖 Number,应逐位模拟竖式加法
  • 双指针从末尾向前扫,或 padStart 对齐后从右向左拼结果
  • 循环条件要覆盖「最后一位仍有进位」的情况
  • 对齐版实现还能统一处理前导零与小整数输入