[{"data":1,"prerenderedAt":498},["ShallowReactive",2],{"blog-big-int-add":3},{"id":4,"title":5,"body":6,"category":103,"date":486,"description":487,"draft":488,"extension":489,"meta":490,"navigation":162,"path":491,"seo":492,"stem":493,"tags":494,"__hash__":497},"blog\u002Fblog\u002Fbig-int-add.md","大整数相加",{"type":7,"value":8,"toc":477},"minimark",[9,12,41,49,53,85,89,100,223,238,242,252,335,350,353,361,364,420,424,431,446,449,452,473],[10,11,5],"h1",{"id":5},[13,14,15,16,20,21,24,25,28,29,32,33,36,37,40],"p",{},"JavaScript 的 ",[17,18,19],"code",{},"Number"," 基于 IEEE 754 双精度浮点，安全整数范围是 ",[17,22,23],{},"-(2^53 - 1)"," 到 ",[17,26,27],{},"2^53 - 1","（即 ",[17,30,31],{},"Number.MAX_SAFE_INTEGER","）。当两个「大正整数」字符串相加时，不能直接用 ",[17,34,35],{},"+"," 或 ",[17,38,39],{},"Number()"," 转换，否则会丢失精度。",[13,42,43,44,48],{},"这道题的核心思路是：",[45,46,47],"strong",{},"模拟小学竖式加法","——从低位到高位逐位相加，维护进位。",[50,51,52],"h2",{"id":52},"思路",[54,55,56,60,63,69,79,82],"ol",{},[57,58,59],"li",{},"将两个操作数转为字符串（或本来就是字符串）",[57,61,62],{},"从最后一位（个位）向前遍历",[57,64,65,66],{},"对应位数字相加，再加上进位 ",[17,67,68],{},"carry",[57,70,71,72,75,76],{},"当前位结果 = ",[17,73,74],{},"sum % 10","，新进位 = ",[17,77,78],{},"Math.floor(sum \u002F 10)",[57,80,81],{},"遍历结束后若仍有进位，需要补一位",[57,83,84],{},"将结果数组反转（或从高位拼接）得到最终字符串",[50,86,88],{"id":87},"实现一数组收集后反转","实现一：数组收集后反转",[13,90,91,92,95,96,99],{},"从字符串末尾双指针向前扫，结果先 ",[17,93,94],{},"push"," 到数组，最后 ",[17,97,98],{},"reverse().join(\"\")","。",[101,102,105],"code-block",{"lang":103,"title":104},"javascript","addBigIntegers",[106,107,111],"pre",{"className":108,"code":109,"language":103,"meta":110,"style":110},"language-javascript shiki shiki-themes github-light github-dark","function addBigIntegers(a, b) {\n  const strA = String(a);\n  const strB = String(b);\n  let i = strA.length - 1;\n  let j = strB.length - 1;\n  let carry = 0;\n  const result = [];\n\n  while (i >= 0 || j >= 0 || carry > 0) {\n    const digitA = i >= 0 ? Number(strA[i--]) : 0;\n    const digitB = j >= 0 ? Number(strB[j--]) : 0;\n    const sum = digitA + digitB + carry;\n    result.push(sum % 10);\n    carry = Math.floor(sum \u002F 10);\n  }\n\n  return result.reverse().join(\"\");\n}\n","",[17,112,113,121,127,133,139,145,151,157,164,170,176,182,188,194,200,206,211,217],{"__ignoreMap":110},[114,115,118],"span",{"class":116,"line":117},"line",1,[114,119,120],{},"function addBigIntegers(a, b) {\n",[114,122,124],{"class":116,"line":123},2,[114,125,126],{},"  const strA = String(a);\n",[114,128,130],{"class":116,"line":129},3,[114,131,132],{},"  const strB = String(b);\n",[114,134,136],{"class":116,"line":135},4,[114,137,138],{},"  let i = strA.length - 1;\n",[114,140,142],{"class":116,"line":141},5,[114,143,144],{},"  let j = strB.length - 1;\n",[114,146,148],{"class":116,"line":147},6,[114,149,150],{},"  let carry = 0;\n",[114,152,154],{"class":116,"line":153},7,[114,155,156],{},"  const result = [];\n",[114,158,160],{"class":116,"line":159},8,[114,161,163],{"emptyLinePlaceholder":162},true,"\n",[114,165,167],{"class":116,"line":166},9,[114,168,169],{},"  while (i >= 0 || j >= 0 || carry > 0) {\n",[114,171,173],{"class":116,"line":172},10,[114,174,175],{},"    const digitA = i >= 0 ? Number(strA[i--]) : 0;\n",[114,177,179],{"class":116,"line":178},11,[114,180,181],{},"    const digitB = j >= 0 ? Number(strB[j--]) : 0;\n",[114,183,185],{"class":116,"line":184},12,[114,186,187],{},"    const sum = digitA + digitB + carry;\n",[114,189,191],{"class":116,"line":190},13,[114,192,193],{},"    result.push(sum % 10);\n",[114,195,197],{"class":116,"line":196},14,[114,198,199],{},"    carry = Math.floor(sum \u002F 10);\n",[114,201,203],{"class":116,"line":202},15,[114,204,205],{},"  }\n",[114,207,209],{"class":116,"line":208},16,[114,210,163],{"emptyLinePlaceholder":162},[114,212,214],{"class":116,"line":213},17,[114,215,216],{},"  return result.reverse().join(\"\");\n",[114,218,220],{"class":116,"line":219},18,[114,221,222],{},"}\n",[13,224,225,226,229,230,233,234,237],{},"注意 ",[17,227,228],{},"while"," 条件里的 ",[17,231,232],{},"carry > 0","：最高位相加后若产生进位（如 ",[17,235,236],{},"999 + 1","），循环需要多跑一轮。",[50,239,241],{"id":240},"实现二左对齐补零高位拼接","实现二：左对齐补零，高位拼接",[13,243,244,245,248,249,99],{},"另一种写法是先去掉前导零、用 ",[17,246,247],{},"padStart"," 对齐长度，再从右向左遍历，把每位结果",[45,250,251],{},"拼到字符串前面",[101,253,255],{"lang":103,"title":254},"addBigIntegers（对齐版）",[106,256,258],{"className":108,"code":257,"language":103,"meta":110,"style":110},"function addBigIntegers(a, b) {\n  a = String(a).replace(\u002F^0+\u002F, \"\") || \"0\";\n  b = String(b).replace(\u002F^0+\u002F, \"\") || \"0\";\n  const lth = Math.max(a.length, b.length);\n  a = a.padStart(lth, \"0\");\n  b = b.padStart(lth, \"0\");\n  let carry = 0;\n  let result = \"\";\n  for (let i = lth - 1; i >= 0; i--) {\n    const sum = Number(a[i]) + Number(b[i]) + carry;\n    carry = Math.floor(sum \u002F 10);\n    result = String(sum % 10) + result;\n  }\n  if (carry > 0) result = String(carry) + result;\n  return result;\n}\n",[17,259,260,264,269,274,279,284,289,293,298,303,308,312,317,321,326,331],{"__ignoreMap":110},[114,261,262],{"class":116,"line":117},[114,263,120],{},[114,265,266],{"class":116,"line":123},[114,267,268],{},"  a = String(a).replace(\u002F^0+\u002F, \"\") || \"0\";\n",[114,270,271],{"class":116,"line":129},[114,272,273],{},"  b = String(b).replace(\u002F^0+\u002F, \"\") || \"0\";\n",[114,275,276],{"class":116,"line":135},[114,277,278],{},"  const lth = Math.max(a.length, b.length);\n",[114,280,281],{"class":116,"line":141},[114,282,283],{},"  a = a.padStart(lth, \"0\");\n",[114,285,286],{"class":116,"line":147},[114,287,288],{},"  b = b.padStart(lth, \"0\");\n",[114,290,291],{"class":116,"line":153},[114,292,150],{},[114,294,295],{"class":116,"line":159},[114,296,297],{},"  let result = \"\";\n",[114,299,300],{"class":116,"line":166},[114,301,302],{},"  for (let i = lth - 1; i >= 0; i--) {\n",[114,304,305],{"class":116,"line":172},[114,306,307],{},"    const sum = Number(a[i]) + Number(b[i]) + carry;\n",[114,309,310],{"class":116,"line":178},[114,311,199],{},[114,313,314],{"class":116,"line":184},[114,315,316],{},"    result = String(sum % 10) + result;\n",[114,318,319],{"class":116,"line":190},[114,320,205],{},[114,322,323],{"class":116,"line":196},[114,324,325],{},"  if (carry > 0) result = String(carry) + result;\n",[114,327,328],{"class":116,"line":202},[114,329,330],{},"  return result;\n",[114,332,333],{"class":116,"line":208},[114,334,222],{},[13,336,337,338,341,342,345,346,349],{},"相比实现一，这版额外处理了",[45,339,340],{},"前导零","（",[17,343,344],{},"\"0123\" + \"456\""," → ",[17,347,348],{},"\"579\"","），对小整数也适用。",[50,351,352],{"id":352},"测试用例",[106,354,359],{"className":355,"code":357,"language":358,"meta":110},[356],"language-text","addBigIntegers(\"999999999999999999999\", \"1\")\n\u002F\u002F → \"1000000000000000000000\"\n\naddBigIntegers(\"12345678901234567890\", \"98765432109876543210\")\n\u002F\u002F → \"111111111011111111100\"\n\naddBigIntegers(123, 456)\n\u002F\u002F → \"579\"\n\naddBigIntegers(\"0123\", \"456\")\n\u002F\u002F → \"579\"\n","text",[17,360,357],{"__ignoreMap":110},[50,362,363],{"id":363},"复杂度与边界",[365,366,367,380],"table",{},[368,369,370],"thead",{},[371,372,373,377],"tr",{},[374,375,376],"th",{},"项目",[374,378,379],{},"说明",[381,382,383,392,400,412],"tbody",{},[371,384,385,389],{},[386,387,388],"td",{},"时间复杂度",[386,390,391],{},"O(max(m, n))，m、n 为两数位数",[371,393,394,397],{},[386,395,396],{},"空间复杂度",[386,398,399],{},"O(max(m, n))，存放结果",[371,401,402,405],{},[386,403,404],{},"负数",[386,406,407,408,411],{},"本题通常只考大",[45,409,410],{},"正","整数；若需支持负数，要先处理符号与绝对值大小比较",[371,413,414,417],{},[386,415,416],{},"小数",[386,418,419],{},"需先对齐小数点，再分别处理整数与小数部分",[50,421,423],{"id":422},"延伸bigint","延伸：BigInt",[13,425,426,427,430],{},"现代环境可直接用 ",[17,428,429],{},"BigInt","：",[106,432,434],{"className":108,"code":433,"language":103,"meta":110,"style":110},"String(BigInt(\"999999999999999999999\") + BigInt(\"1\"))\n\u002F\u002F → \"1000000000000000000000\"\n",[17,435,436,441],{"__ignoreMap":110},[114,437,438],{"class":116,"line":117},[114,439,440],{},"String(BigInt(\"999999999999999999999\") + BigInt(\"1\"))\n",[114,442,443],{"class":116,"line":123},[114,444,445],{},"\u002F\u002F → \"1000000000000000000000\"\n",[13,447,448],{},"面试手写时仍建议掌握字符串模拟竖式加法——考察的是对进位、边界和字符串操作的理解，而非 API 记忆。",[50,450,451],{"id":451},"小结",[453,454,455,461,467,470],"ul",{},[57,456,457,458,460],{},"大整数相加不能依赖 ",[17,459,19],{},"，应逐位模拟竖式加法",[57,462,463,464,466],{},"双指针从末尾向前扫，或 ",[17,465,247],{}," 对齐后从右向左拼结果",[57,468,469],{},"循环条件要覆盖「最后一位仍有进位」的情况",[57,471,472],{},"对齐版实现还能统一处理前导零与小整数输入",[474,475,476],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":110,"searchDepth":129,"depth":129,"links":478},[479,480,481,482,483,484,485],{"id":52,"depth":123,"text":52},{"id":87,"depth":123,"text":88},{"id":240,"depth":123,"text":241},{"id":352,"depth":123,"text":352},{"id":363,"depth":123,"text":363},{"id":422,"depth":123,"text":423},{"id":451,"depth":123,"text":451},"2026-05-10","用字符串模拟竖式加法，处理超出 Number 精度的大正整数求和，常见前端面试手写题。",false,"md",{},"\u002Fblog\u002Fbig-int-add",{"title":5,"description":487},"blog\u002Fbig-int-add",[495,496],"algorithm","interview","AzJ9a1SGNrgKuH7mn3OfWWWrm1n9SCy5pVODYzyS9W4",1782309645712]