javascript中0.1+0.2不等于0.3,因其采用ieee 754双精度浮点数表示,0.1和0.2在二进制中为无限循环小数,经52位尾数截断后产生舍入误差,相加时误差叠加导致结果为0.30000000000000004。

因为 JavaScript 中所有数字都用 IEEE 754 双精度浮点数表示,而 0.1 和 0.2 在二进制下是无限循环小数,无法被 52 位尾数精确存储,相加后误差叠加,结果是 0.30000000000000004,不是严格等于 0.3。
JavaScript 只有一种数字类型:Number
JS 没有 int、float、double 等区分,所有数值统一为 64 位双精度浮点数(遵循 IEEE 754 标准):1 位符号位 + 11 位指数位 + 52 位尾数位。这意味着即使是整数(如 42),底层也按浮点格式存储和运算。这种设计简化了引擎实现,但也继承了浮点数的全部特性——包括精度限制。
0.1 和 0.2 的二进制表示天生不精确
十进制小数能否被有限位二进制准确表达,取决于它是否能写成若干个 1/(2ⁿ) 的和。例如:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
-
0.5 = 1/2 = 0.1₂→ 精确 -
0.25 = 1/4 = 0.01₂→ 精确 -
0.1无法写成有限个1/2, 1/4, 1/8...之和 → 二进制为0.00011001100110011…(循环节0011)→ 必须截断到 52 位 → 引入舍入误差 -
0.2同理,也是无限循环二进制 → 同样被截断,产生另一个独立误差
误差在计算中会叠加和放大
两个近似值相加时,不仅各自带误差,还要经历对阶(align exponent)、尾数相加、规格化、再舍入等步骤。比如:
-
0.1实际存储值略大于 0.1(约 +5.55e−17) -
0.2实际存储值也略大于 0.2(约 +1.11e−16) - 两者相加后,总偏差约 +1.66e−16 → 表现为
0.30000000000000004 - 而
0.3本身在存储时被舍入为略小的值 → 进一步拉大了“相等”判断的差距
这不是 JS 的 bug,而是通用计算限制
该现象在 Python、Java、C、Go 等几乎所有使用 IEEE 754 的语言中都会出现。它源于硬件层面的数学现实:用有限位二进制表达某些十进制小数,本身就是不可能的任务。就像十进制无法精确写出 1/3 = 0.333… 一样,二进制也无法精确写出 0.1。
真正需要关注的是如何应对——金融计算常用整数 cents 避开小数,前端展示可用 toFixed(1) 或 Number.EPSILON 比较,高精度场景推荐 BigInt(整数)或专用库如 decimal.js。










