javascript中number类型因ieee 754精度限制,安全整数范围为±9007199254740991,超限会导致精度丢失;大数运算需用字符串模拟竖式加法,逐位计算并处理进位,以实现原始数值精确表示。

JavaScript 中的 Number 类型基于 IEEE 754 双精度浮点数,安全整数范围是 -(2^53 - 1) 到 2^53 - 1(即 ±9007199254740991)。超出此范围后,整数精度丢失,无法准确表示或运算。要模拟“原始数值”(即保持每一位数字精确),必须绕过原生数字类型,改用字符串或数组来存储和计算大整数——这就是大数相加算法的核心思路。
为什么不能直接用 JavaScript 数字类型?
不是因为“不能存”,而是“存不准”。例如:
9007199254740991 + 1 === 9007199254740992 ✅9007199254740992 + 1 === 9007199254740992 ❌(实际被舍入)
这是因为第 54 位及之后的二进制位已无足够精度表示,底层浮点数表示发生了隐式舍入。所以,**原始数值模拟 = 摒弃 Number,手写十进制竖式加法逻辑**。
字符串模拟:从右到左逐位相加
将两个超长数字转为字符串,按小学加法方式从个位开始相加,维护进位(carry),拼接结果字符:
- 对齐两字符串(可左补零,或从末尾索引倒推)
- 用指针
i、j分别指向两数末尾,carry = 0 - 循环直到两指针都越界且
carry === 0 - 每轮:取当前位数字(
parseInt(a[i] || '0')),加carry,更新sum % 10为当前位结果,Math.floor(sum / 10)为新carry - 将结果字符
unshift或反向拼接(避免频繁字符串拼接可用数组)
✅ 支持任意长度非负整数;❌ 需额外处理符号、前导零、空输入等边界。
支持负数与减法:扩展为大数四则基础库
仅加法不够“原始数值模拟”——真实场景需完整算术。关键策略:
- 统一预处理符号:提取正负号,转为两个非负字符串参与运算
- 加法:同号直接调用字符串加法;异号转为「大减小」并赋予符号
- 减法:实现
subtract(a, b),核心是借位逻辑(从右往左,不够则向前借 10) - 比较大小:先比长度,等长时字典序比较(注意不能直接用
>,因是字符串)
例如:subtract("1000", "999") → 先比长度相等,再逐位借位,得 "1"。
生产可用建议:用成熟库 or 自研权衡
若项目需可靠、全场景(含乘除、负数、小数、性能优化),推荐轻量库:
-
big-integer:专为大整数设计,API 简洁(
BigInteger("123").add("456")),不依赖浮点 -
bigint(ES2020+):原生
123n + 456n,但仅支持整数,且typeof是"bigint",与Number不互通,需显式转换 - 自研仅推荐学习/极简场景:如只做加法、输入可控、无性能压力
注意:BigInt 虽原生高效,但它仍是独立类型——若你目标是“完全模拟原始十进制字符串行为”(比如保留前导零、自定义进制、或与服务端字符串数值无缝对接),字符串方案反而更透明可控。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











