0.1+0.2

本文探讨了在JavaScript中0.1加0.2不等于0.3的现象,揭示了这是由于计算机内部使用IEEE754标准存储浮点数导致的普遍问题。详细解析了双精度浮点数的结构,并通过实例说明了0.1和0.2在计算机中的实际表示。
在看js 的过程中发现了0.1加0.2不等于0.3,查了半天资料,总结一下免得忘记了…
可以阅读英文原文参考资料:参考资料

这个问题不仅仅存在于js,其他很多语言也有这个问题,这是使用基于IEEE754 数值的浮点计算的通病。

1.小数在计算机中的表示

首先,小数在计算机中按照二进制保存,如 0.5 表示为 0.1(2的-1次方) ,0.125表示为 0.001 (2 的 -3次方)。但是小数如果不是这些可以被2的负多少次方表示的数,那么二进制可能无法在有限位精确表示。

如0.1(十进制)表示为二进制就是:0.0001100110011001…

在IEEE754浮点数中,分为双精度和单精度两种类型,单精度32个比特存储,双精度浮点数64个比特存储。

这里讨论双精度小数。双精度小数64位按照科学计数法来保存小数。

由以下三部分组成(Sign:符号位 Exponent:指数位 Mantissa:尾数位)

在这里插入图片描述

Sign 符号位:

表示正负

Exponent 指数位:

数字的含义我的理解是 2的次方数。如指数位算出来是4就是二进制的2次方,是8就是二进制的三次方。
在这里插入图片描述
这里应该有11位,多一个指数位的符号位。所以二进制的-2次方指数位表示为 01111111011.

Mantissa尾数位:

保存的二进制数字,默认科学计数法第一个有效数字必定是1,因此这个1不储存。最大保存52位。

2. 0.1在计算机中的表示

0.1的二进制计算方式如下:
在这里插入图片描述
将每次乘2的整数位记录下来即0.1的二进制表示,计算如下:
在这里插入图片描述
那么写成科学计数法,表示如下:
在这里插入图片描述
指数位计算按照刚才所写,计算为:01111111011.
所以 64位 的 0.1 表示为:[符号位][尾数位][指数位]:
在这里插入图片描述
同理 0.2等于:在这里插入图片描述
加起来等于:
在这里插入图片描述

转换为十进制则为0.30000000000000004.

### 浮点数运算精度问题 在 JavaScript 中,`0.1 + 0.2` 的结果并不是 `0.3`,而是 `0.30000000000000004`。这一现象并不是 JavaScript 特有的,而是许多编程语言在处理浮点数时都会遇到的问题[^1]。 JavaScript 使用 IEEE 754 标准来表示浮点数,这种标准使用二进制浮点数格式来存储小数值。由于某些十进制小数无法用有限的二进制小数精确表示,因此在转换和计算过程中会出现精度丢失的问题。例如,`0.1` 和 `0.2` 在二进制表示中都是无限循环小数,无法被精确存储[^2]。 以下是一个简单的代码示例: ```javascript console.log(0.1 + 0.2); // 输出 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // 输出 false ``` ### IEEE 754 标准与浮点数表示 IEEE 754 标准定义了浮点数的存储和计算方式。在 JavaScript 中,所有数字都是 64 位(双精度)浮点数,这意味着每个数字都按照 IEEE 754 双精度格式进行存储和计算。由于二进制浮点数的精度有限,某些十进制数值在转换为二进制时会出现无限循环,导致精度丢失[^3]。 例如,`0.1` 在二进制中表示为 `0.00011001100110011...`,这是一个无限循环小数。由于计算机只能存储有限位数,因此只能近似表示,这导致了精度问题。 ### 如何处理浮点数精度问题 在实际开发中,如果需要进行高精度的数值计算,可以采用以下几种方法: 1. **使用库进行精确计算**:如 `decimal.js` 或 `big.js` 等库可以提供更高精度的数学运算。 2. **避免直接比较浮点数**:可以使用一个极小的误差值(如 `Number.EPSILON`)来判断两个浮点数是否“足够接近”: ```javascript function isEqual(a, b) { return Math.abs(a - b) < Number.EPSILON; } console.log(isEqual(0.1 + 0.2, 0.3)); // 输出 true ``` 3. **使用整数运算代替浮点数运算**:例如,将金额转换为分(cents)进行计算,最后再转换为元(dollars)。 ### 总结 JavaScript 中的浮点数运算问题源于 IEEE 754 标准的二进制表示限制,并非语言本身的缺陷。开发者可以通过使用高精度计算库、避免直接比较浮点数或转换为整数运算等方式来解决这一问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值