为什么 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
相关推荐
2401_885885047 分钟前
巴林语音通知接口如何对接?系统告警语音API接入教程
android·前端·网络·python·语音识别
java1234_小锋7 分钟前
【技术专题】CSS3 网页技术 - CSS3 盒模型
前端·css·css3
计算机魔术师10 分钟前
手握芯片、又要吞下开源分发入口,英伟达被盯上了
前端
段一凡-华北理工大学41 分钟前
高炉能源系统智能化:热风炉、煤气与极致能效~系列文章07:高炉煤气:产生规律与全厂用户平衡
java·前端·能源
牧瀬クリスだ1 小时前
Redis Hash实战:高效存储对象与购物车
java·数据库·redis·算法·哈希算法
程序员大阳1 小时前
副队长JavaScript教程(55)-DOM节点增删改查
javascript·dom·增删改查·节点·克隆
木井巳1 小时前
【动态规划: 路径问题】下降路径最小和
java·算法·leetcode·动态规划·推荐算法
前端架构师-老李1 小时前
HTML与CSS基础第四课—strong、em、b、i 各表示什么
前端·css·html
king王一帅2 小时前
AI 时代一群人在卷笔记软件,我想先把 Markdown 编辑器的底层做好
前端·ai编程·markdown
用户11481867894842 小时前
盲水印:DCT-QIM 从原理到踩坑
前端