JavaScript大数精度问题源于Number类型限制,安全整数范围为−2⁵³+1至2⁵³−1;应优先用BigInt处理超大整数,用decimal.js或big.js处理高精度小数,后端应将长整型转字符串输出以源头规避精度丢失。

JavaScript 处理大数精度问题,核心在于认清 Number 类型的固有限制:它本质是 IEEE 754 双精度浮点数,能精确表示的整数范围仅限于 −2<sup>53</sup> + 1 到 2<sup>53</sup> − 1(即 Number.MAX_SAFE_INTEGER === 9007199254740991)。超出此范围的整数(如雪花 ID、长订单号、区块链哈希、高精度时间戳)在解析、运算或比较时就会悄然失真。
用 BigInt 安全处理超大整数
ES2020 起,原生支持 BigInt,专为任意位数整数设计,无精度损失:
- 声明方式:末尾加
n(如1965951881494065154n),或调用BigInt("字符串");字符串入参是必须的,避免 Number 初始化阶段就丢精度 - 运算限制:不能与普通
Number混算,需显式转换,例如BigInt(123) + 456n合法,但123n + 456会报错 - 适用场景:ID 存储、计数器、位运算、加密计算等纯整数逻辑;不支持小数、
Math方法、JSON.stringify直接序列化(需手动转字符串)
用 decimal.js 或 big.js 处理高精度十进制运算
当涉及金额、利率、科学数据等需要小数精度的场景,BigInt 不适用,应选专注十进制的库:
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
-
decimal.js功能最全:支持三角函数、幂、对数、配置舍入模式和精度位数,适合金融系统 -
big.js更轻量(约 6KB)、API 简洁、不可变设计,推荐用于电商价格计算、表单校验等常规业务 - 关键实践:所有初始化务必用字符串,如
new Decimal("0.1").plus("0.2"),杜绝new Decimal(0.1)—— 后者传入时 0.1 已失真
后端协同:让数字“别变成 Number”
精度丢失常发生在 JSON 解析一瞬。最彻底的解法不是前端硬扛,而是源头规避:
立即学习“Java免费学习笔记(深入)”;
- 后端序列化时将长整型字段(如 Java 的
Long、MySQL 的BIGINT)转为字符串输出,例如 Jackson 加@JsonSerialize(using = ToStringSerializer.class) - 前端收到后直接当字符串使用(如作为 API 请求参数、路由 ID、本地缓存 key),无需解析为数字
- 若需展示,可用
Intl.NumberFormat格式化字符串,既保精度又提升可读性
避免踩坑的实用习惯
不依赖直觉,建立防御性编码意识:
- 对任何可能超 16 位的数字(尤其是 ID、时间戳毫秒值),默认按字符串收、按字符串传
- 禁止用
==或===直接比较两个大数字符串或 BigInt,先统一类型再比;123n === BigInt("123")为 true,但123n === 123为 false - 警惕
JSON.parse自动转数字行为,必要时用 reviver 函数拦截并转成 BigInt 或字符串

















