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

3. 为什么 0.1 + 0.2 != 0.3

总结

  1. 底层是二进制实现

概述

在 JavaScript 中,0.1 + 0.2 的结果并不是精确的 0.3,而是 0.30000000000000004。这个现象并不是 JavaScript 的“bug”,而是由于浮点数在计算机底层的二进制表示方式导致的精度丢失问题。


一、计算机如何表示小数?

JavaScript 使用 IEEE 754 标准中的 64 位双精度浮点数(double) 来表示数字。这种格式将一个数字分为三部分:

  • 符号位(Sign bit):1 位,表示正负。
  • 指数位(Exponent):11 位,表示数值范围。
  • 尾数位(Mantissa / Fraction):52 位,表示精度。

由于计算机只能使用有限位数的二进制来表示小数,因此某些十进制小数无法被精确表示为二进制浮点数


二、为什么 0.10.2 无法精确相加?

1. 十进制转二进制的小数部分是无限循环

  • 0.1(十进制) → 0.00011001100110011...(二进制,无限循环)
  • 0.2(十进制) → 0.0011001100110011...(二进制,无限循环)

由于只能保留有限位(52 位尾数),因此只能近似存储这些值。

2. 计算时产生误差累积

当计算机将这两个近似值相加时,误差也随之累积,最终结果为:

0.1 + 0.2;
// 输出:0.30000000000000004

三、IEEE 754 表示举例

0.1 为例,其 IEEE 754 表示如下(简化):

部分
符号位0(正数)
指数位-4(即 2^-4)
尾数位1.10011001100110011001101…(截断后)

最终得到的值是:1.10011001100110011001101 × 2^-4,并不是精确的 0.1


四、其他语言也存在这个问题吗?

是的,所有使用 IEEE 754 浮点数标准的语言都存在这个问题,例如:

  • Python
  • Java
  • C++
  • Go
>>> 0.1 + 0.2
0.30000000000000004

五、如何解决精度问题?

1. 使用 toFixed() + parseFloat()

parseFloat((0.1 + 0.2).toFixed(1)) === 0.3;
// true

⚠️ 注意:toFixed() 返回字符串,需用 parseFloat() 转换回数字。

2. 使用 decimal.jsbig.js 等库

对于金融计算或高精度需求,推荐使用第三方库:

npm install decimal.js
import Decimal from "decimal.js";const result = new Decimal(0.1).plus(new Decimal(0.2));
result.equals(0.3); // true

3. 乘以 10^n 转换为整数运算

function add(a, b, precision = 10) {return (a * precision + b * precision) / precision;
}add(0.1, 0.2); // 0.3

http://www.xdnf.cn/news/1248841.html

相关文章:

  • 多传感器融合
  • Redis之Set和SortedSet类型常用命令
  • leetcode-python-删除链表的倒数第 N 个结点
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-邮箱重置密码
  • 使用ProxySql实现MySQL的读写分离
  • ubuntu24安装vulkan-sdk
  • 一文搞定JavaServerPages基础,从0开始写一个登录与人数统计页面
  • Rust进阶-part4-智能指针2
  • 力扣106:从中序与后序遍历序列构造二叉树
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-登录实现
  • Redis里面什么是sdshdr,可以详细介绍一下吗?
  • Linux lvm逻辑卷管理
  • 跑yolov5的train.py时,ImportError: Failed to initialize: Bad git executable.
  • 【Linux】特效爆满的Vim的配置方法 and make/Makefile原理
  • 一种红外遥控RGB灯带控制器-最低价MCU
  • MySQL间隙锁在查询时锁定的范围
  • 前端遇到页面卡顿问题,如何排查和解决?
  • 【运维部署篇】OpenShift:企业级容器应用平台全面解析
  • Spring 的优势
  • Springboot集成Log4j2+MDC串联单次请求的日志
  • HBM Basic(VCU128)
  • 《Python基础》第3期:使用PyCharm编写Hello World
  • Leetcode-2080区间内查询数字的频率
  • 查看部署在K8S服务的资源使用情况
  • LOOP Finance:一场 Web3 共和国中的金融制度实验
  • 创维智能融合终端DT741_移动版_S905L3芯片_安卓9_线刷固件包
  • Linux驱动24 --- RkMedia 视频 API 使用
  • 前端保持和服务器时间同步的方法【使用vue3举例】
  • Tasks and Deadlines(Sorting and Searching)
  • Mysql-事务