为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?

这是 JavaScript 面试中非常经典的问题,本质上不是 0.1 + 0.2 算错了,而是 IEEE 754 浮点数无法精确表示某些十进制小数。

1. 为什么 0.1 + 0.2 !== 0.3?

JavaScript 的 Number 使用 IEEE 754 双精度浮点数(64 bit) 。

十进制的 0.1、0.2 在二进制中都是无限循环小数:

scss 复制代码
0.1 (十进制)
↓
0.000110011001100110011... (二进制)

所以 JavaScript 只能存储它们的近似值。

实际上可以近似理解为:

复制代码
0.1 ≈ 0.10000000000000000555
0.2 ≈ 0.20000000000000001110

两者相加
≈ 0.30000000000000004441

因此:

arduino 复制代码
0.1 + 0.2 === 0.3
// false

console.log(0.1 + 0.2)
// 0.30000000000000004

而 0.3 本身也只是一个接近 0.3 的浮点数,只是它和 0.1 + 0.2 最终得到的浮点表示不同。


2. 最常用的解决方案:误差范围比较

如果是普通数值计算,推荐使用误差范围:

javascript 复制代码
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON
// true

更实用一点,可以封装:

javascript 复制代码
function nearlyEqual(a, b, epsilon = Number.EPSILON) {
  return Math.abs(a - b) < epsilon;
}

nearlyEqual(0.1 + 0.2, 0.3);
// true

不过要注意:对于特别大或特别小的数字 ,固定 Number.EPSILON 不一定合适,工程中通常会使用相对误差。


3. 金融金额:不要直接用浮点数

例如:

ini 复制代码
const price = 0.1;
const quantity = 3;

console.log(price * quantity);

如果涉及金额、订单、支付、财务计算,更推荐把金额转换成整数的最小单位。

例如人民币使用"分":

ini 复制代码
const price = 10; // 0.10 元 = 10 分
const quantity = 3;

const total = price * quantity;

console.log(total / 100);
// 0.3

也就是说:

复制代码
0.1 元 → 10 分
0.2 元 → 20 分
0.3 元 → 30 分

整数计算就不会产生这种浮点误差。


4. 需要精确小数计算:使用 Decimal 库

例如使用 decimal.js:

sql 复制代码
import Decimal from 'decimal.js';

const result = new Decimal('0.1')
  .plus(new Decimal('0.2'));

console.log(result.toString());
// "0.3"

这里特别注意:

scss 复制代码
new Decimal(0.1)

不如:

sql 复制代码
new Decimal('0.1')

因为如果你先把 0.1 作为 JavaScript Number 创建出来,浮点误差已经产生了。


5. 现代 JavaScript 还可以考虑 BigInt

BigInt 可以精确处理整数:

ini 复制代码
const a = 10000000000000000n;
const b = 20000000000000000n;

console.log(a + b);
// 30000000000000000n

但它不能直接处理小数:

arduino 复制代码
0.1n // SyntaxError

所以金额场景依然通常是:

复制代码
0.1 元 → 10n 分

而不是直接存储小数。


面试可以这样回答

JavaScript 的 Number 使用 IEEE 754 双精度浮点数,0.1 和 0.2 无法在二进制浮点格式中被精确表示,只能存储近似值,所以两者相加得到的结果与 0.3 的浮点表示并不完全相同。

普通计算可以使用误差范围比较,例如 Math.abs(a - b) < Number.EPSILON;涉及金额等精确小数计算时,应该使用整数最小单位,或者使用 Decimal 等高精度计算库。

一句话记忆:

markdown 复制代码
0.1 + 0.2 !== 0.3
        ↓
IEEE 754 浮点数精度问题
        ↓
普通计算 → 误差比较
金额计算 → 整数分/厘
高精度小数 → Decimal
相关推荐
HEJOO91 小时前
Linux 设备驱动系列——使用全局工作队列
java·linux·算法
Code_Solitude1 小时前
c语言:递归
java·c语言·算法
掘金酱2 小时前
[稀土掘金 × 火山引擎] AI用量周榜冲刺赛|获奖名单公示
前端·人工智能·后端
泡泡oO2 小时前
“如果你还在用Superpowers,那我不要和你说话”
前端·后端·全栈
维克兜率天2 小时前
趋势过滤:避免被“假突破“反复打脸
前端
edtoplort2 小时前
OpenAI紧急叫停GPT-6.1 Astra训练,奥尔特曼为何踩刹车
人工智能·gpt·算法
蒜香可达鸭2 小时前
让视频生成流水线跑不崩:一个事件溯源的多 Agent 可靠执行框架
算法
8年区块链老兵2 小时前
一篇文章教会你:用区块高度读懂比特币链上的每一笔交易
前端
xixichensh3 小时前
前端转做AI程序员第一步——开发一个AI流式对话Demo
前端