当前位置: 首页 > news >正文

0.1加0.2为什么不等于0.3

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

这个问题你可能在面试、线上 Bug、甚至随手写 Demo 的时候都见过:

console.log(0.1 + 0.2 === 0.3); // false

很多人第一反应是“浮点数精度问题”,但如果继续追问:

  • 为什么偏偏是 0.10.2 这种小数出问题?
  • “精度”到底精在哪一位、丢在哪一步?
  • 实际开发里应该怎么比较、怎么计算才稳?

这篇文章按“现象 → 原因 → 解决 → 面试回答”的顺序,把它讲透。

先看现象

console.log(0.1 + 0.2);  // 0.30000000000000004
console.log(0.1 + 0.7);  // 0.7999999999999999
console.log(0.3 - 0.2);  // 0.09999999999999998
console.log(0.1 * 3);    // 0.30000000000000004
但有些计算又是对的:
console.log(0.5 + 0.5);    // 1
console.log(0.25 + 0.25);  // 0.5
console.log(0.125 * 8);    // 1

为什么?

根本原因:二进制无法精确表示某些十进制小数

计算机用二进制存储数字。十进制的 0.5 在二进制里是 0.1,能精确表示。但十进制的 0.1 在二进制里是:

0.0001100110011001100110011001100110011... (无限循环)

就像十进制里 1/3 = 0.333... 无限循环一样,0.1 在二进制里也是无限循环的。

但计算机内存有限,不能存无限长的数字,必须在某个位置截断。JavaScript 用的是 IEEE 754 双精度浮点数,只有 64 位,其中 52 位用来存小数部分。

截断就意味着误差。

哪些数能精确表示?

能被 2 的幂次整除的小数,在二进制里都能精确表示:

// 这些都是精确的
0.5   = 1/2     = 0.1 (二进制)
0.25  = 1/4     = 0.01 (二进制)
0.125 = 1/8     = 0.001 (二进制)
0.0625 = 1/16  = 0.0001 (二进制)

而 0.1 = 1/10,10 = 2 × 5,有因子 5,所以在二进制里是无限循环。

规律:分母只包含因子 2 的分数,在二进制里能精确表示。

怎么解决?

方案一:容差比较(推荐)

既然有误差,那就别用 === 比较,改用"误差小于某个值":

function isEqual(a, b) {return Math.abs(a - b) < Number.EPSILON;
}console.log(isEqual(0.1 + 0.2, 0.3)); // true

Number.EPSILON 是 JavaScript 里最小的可表示精度差,约等于 2.22e-16。

方案二:转成整数算

小数不精确,整数是精确的。把小数转成整数,算完再转回来:

// 0.1 + 0.2
const result = (0.1 * 10 + 0.2 * 10) / 10;  // 0.3// 封装一下
function add(a, b) {const precision = Math.max((a.toString().split('.')[1] || '').length,(b.toString().split('.')[1] || '').length);const factor = Math.pow(10, precision);return (Math.round(a * factor) + Math.round(b * factor)) / factor;
}console.log(add(0.1, 0.2)); // 0.3

方案三:toFixed 四舍五入

简单粗暴,直接四舍五入:

const result = parseFloat((0.1 + 0.2).toFixed(10));
console.log(result); // 0.3

注意 toFixed 返回的是字符串,要用 parseFloat 转回数字。

方案四:用专门的库

金融计算这种对精度要求高的场景,用专门的库:

// decimal.js
import Decimal from 'decimal.js';const a = new Decimal(0.1);
const b = new Decimal(0.2);
console.log(a.plus(b).toString()); // "0.3"

实际开发中怎么选?

面试怎么答?

JavaScript 用 IEEE 754 双精度浮点数存储数字。十进制的 0.1 在二进制里是无限循环小数,但只有 52 位存储空间,必须截断,所以有精度损失。0.1 和 0.2 存储时都有微小误差,加起来误差累积,结果就不等于 0.3 了。

解决方案有几种:比较时用容差比较、计算时转成整数、或者用 decimal.js 这样的高精度库。

如果面试官继续问"IEEE 754 是什么",可以补充:

IEEE 754 是浮点数的存储标准,用 64 位存一个数字:1 位符号位、11 位指数位、52 位尾数位。这个标准是为了让不同计算机上的浮点运算结果一致。

一道相关的坑题

console.log(0.1 + 0.2 - 0.3); // ?

答案不是 0,而是 5.551115123125783e-17

再来一道:

console.log(9999999999999999); // ?

答案是 10000000000000000。因为超出了安全整数范围(2^53 - 1),精度丢失了。

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

http://www.jsqmd.com/news/268154/

相关文章:

  • 从布局分析到元素识别|基于PaddleOCR-VL的全流程技术拆解
  • NewBie-image-Exp0.1与Mochi Diffusion对比:长尾特征生成能力评测
  • 小程序毕设选题推荐:基于springboot+微信小程序的考研刷题平台考研复习辅助平台【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 如何通过工业智造超级智能体实现汽车制造工厂数字化转型
  • Youtu-2B影视创作:剧本构思与对白生成
  • 从零开始:用Qwen2.5-0.5B-Instruct打造个人AI助手
  • 【必学收藏】DeepSeek Engram新突破:通过可扩展查找实现条件记忆,开启大模型稀疏化新方向
  • Fun-ASR-MLT-Nano-2512语音模型压缩:量化与剪枝实战
  • 【收藏必学】AI大模型入行攻略:避开弯路,掌握实用技能,轻松入行
  • 快速掌握Android init.rc配置,启动脚本轻松集成
  • 必收藏!RAG与Agentic RAG全解析:从基础到进阶,解锁大模型实用能力
  • 2026年挂具脱漆炉推荐:鱼台光华环保科技挂具脱漆炉设备/原理/报价/定制全解析
  • vLLM部署HY-MT1.5-7B指南|高性能翻译模型落地实践
  • 腾讯云TI-ONE平台部署图片旋转判断模型指南
  • DeepSeek-R1-Distill-Qwen-1.5B部署省50%成本?真实案例分享
  • ADAS软件开发
  • 服务CPU突然飙到100%,用Arthas三分钟定位到问题代码
  • 2026年热门的/有实力的/质量好的/正规的/高品质的蒸发器厂家权威推荐榜:聚焦节能、高粘度处理与工业废水净化
  • 高精地图车端引擎开发
  • 2026年起重电磁铁厂家推荐:山磁智能科技有限公司,正面吊/吊运管坯用/吊运捆扎棒材用/吊运钢管用/吊运中厚钢板坯用/吊运方坏用起重电磁铁全系供应
  • 压路机远程监控智慧运维系统解决方案
  • 2026年广州财税记账公司推荐榜:财税公司 /财税代理/ 财税服务 /外包财税 /财税外包 /财税服务外包/ 财税外包公司服务精选
  • 小白指南:elasticsearch安装+Kibana日志展示
  • 2026年资产管理系统软件清单:大型集团+不动产管理优质选择 - 品牌2026
  • 看效果说话:通义千问3-4B生成的80万字长文展示
  • paperzz AI PPT:从 0 到 1 搞定专业演示,告别熬夜改稿的神器
  • UDS 31服务安全访问机制深度剖析:全面讲解
  • 2026年北京继承遗嘱纠纷律师服务推荐:合同纠纷 /交通事故纠纷 /房屋买卖纠纷/ 民间借贷纠纷/ 民事离婚纠纷/ 劳动工伤纠纷律师精选
  • 学术安全盾:paperzz 降重 / 降 AIGC 双重守护你的论文原创性
  • 2026年苏州婚纱摄影机构推荐榜:姑苏区星纳摄影店,苏州婚纱摄影工作室/苏州婚纱摄影拍摄基地/苏州婚纱摄影礼服/苏州婚纱摄影拍摄机构精选