JavaScript数字精度问题源于IEEE 754规范,0.1+0.2≠0.3是必然现象;应分层应对:输入阶段用正则校验和Number()避免误差,计算阶段优先整数运算或decimal.js库,输出阶段仅作视图格式化。

JavaScript 数字精度问题不是 bug,而是 IEEE 754 双精度浮点数规范的自然结果——0.1 + 0.2 !== 0.3 是必然现象。优雅处理的关键,在于不硬扛浮点缺陷,而是按场景分层应对:输入控住、计算隔离、输出可控。
输入阶段:从源头掐断误差
用户一敲小数点,精度风险就开始累积。别等计算完再“修”,要提前拦截。
- 对金额类输入,用
inputmode="decimal"+ 正则校验(如/^\d+(\.\d{1,2})?$/),禁止三位以上小数或非法字符 - 避免直接
parseFloat(input.value)——它会静默截断"1.23abc"成1.23;改用Number()或先正则提取再转 - 粘贴长数字时,监听
paste事件并做格式清洗,防止原始字符串直接进入计算流
计算阶段:绕开浮点,优先整数或封装安全运算
一旦数值进入业务逻辑,就别让它以原生 Number 形式参与四则运算。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 金额/计数等固定小数位场景,统一放大为整数:元 → 分(×100)、米 → 毫米(×1000),全程整数加减,最后仅在展示时还原
- 通用小数(如折扣率、权重),可用轻量函数封装放大还原逻辑:
先取两数最大小数位数n,乘10ⁿ取整,加减后再除回,且必须用Math.round()防放大误差 - 严禁在中间步骤用
toFixed()修正数值——它返回字符串,且舍入是银行家舍入(1.005.toFixed(2) === "1.00"),会引入新偏差
高精度需求:交给 decimal.js 这类专业库
当涉及多位小数、金融级计算、科学运算或超过 15 位有效数字时,原生类型已不可靠。
- 推荐
decimal.js:轻量、API 清晰、默认精度 20,支持显式设置(如Decimal.set({ precision: 30 }))和多种舍入模式 - 创建实例时务必传字符串(
new Decimal('0.1')),避免new Decimal(0.1)—— 后者传入时精度已丢失 - 所有中间运算保持
Decimal实例,最终需转字符串输出(.toString()),切勿转回Number,否则前功尽弃
输出阶段:只用于展示,不参与后续计算
最终呈现给用户的数字,可以放心格式化,但必须明确这是纯视图行为。
- 用
(num).toFixed(2)得到字符串,再用parseFloat()或+str转回数字——仅限该值不再参与任何后续运算时才这么做 - 若需严格数学四舍五入(非银行家舍入),自己实现:
function roundTo(num, digits) { const d = 10 ** digits; return Math.round(num * d) / d; } - 比较两个浮点数是否“相等”?别用
===,改用差值绝对值小于容差(如Math.abs(a - b) )
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










