全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

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

发布时间:2022-10-05 21:44:00
发布人:wjy

  在开发过程中遇到类似这样的问题:

为什么0.1+0.2 ! == 0.31

  这里得到的不是想要的结果,要想等于0.3,就要把它进行转化:

为什么0.1+0.2 ! == 0.3 2

  toFixed(num) 方法可把 Number 四舍五入为指定小数位数的数字。那为什么会出现这样的结果呢?

  计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。0.1的二进制是0.0001100110011001100...(1100循环),0.2的二进制是:0.00110011001100...(1100循环),这两个数的二进制都是无限循环的数。那JavaScript是如何处理无限循环的二进制小数呢?

  一般我们认为数字包括整数和小数,但是在 JavaScript 中只有一种数字类型:Number,它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留52位,再加上前面的1,其实就是保留53位有效数字,剩余的需要舍去,遵从“0舍1入”的原则。

  根据这个原则,0.1和0.2的二进制数相加,再转化为十进制数就是:0.30000000000000004。

  下面看一下双精度数是如何保存的:

为什么0.1+0.2 ! == 0.3 3

  第一部分(蓝色):用来存储符号位(sign),用来区分正负数,0表示正数,占用1位第二部分(绿色):用来存储指数(exponent),占用11位第三部分(红色):用来存储小数(fraction),占用52位

  对于0.1,它的二进制为:

为什么0.1+0.2 ! == 0.3 4

  转为科学计数法(科学计数法的结果就是浮点数):

为什么0.1+0.2 ! == 0.3 5

  可以看出0.1的符号位为0,指数位为-4,小数位为:

为什么0.1+0.2 ! == 0.3 6

  那么问题又来了,指数位是负数,该如何保存呢?

  IEEE标准规定了一个偏移量,对于指数部分,每次都加这个偏移量进行保存,这样即使指数是负数,那么加上这个偏移量也就是正数了。由于JavaScript的数字是双精度数,这里就以双精度数为例,它的指数部分为11位,能表示的范围就是0~2047,IEEE固定双精度数的偏移量为1023。

  当指数位不全是0也不全是1时(规格化的数值),IEEE规定,阶码计算公式为 e-Bias。 此时e最小值是1,则1-1023= -1022,e最大值是2046,则2046-1023=1023,可以看到,这种情况下取值范围是-1022~1013。当指数位全部是0的时候(非规格化的数值),IEEE规定,阶码的计算公式为1-Bias,即1-1023= -1022。当指数位全部是1的时候(特殊值),IEEE规定这个浮点数可用来表示3个特殊值,分别是正无穷,负无穷,NaN。 具体的,小数位不为0的时候表示NaN;小数位为0时,当符号位s=0时表示正无穷,s=1时候表示负无穷。

  对于上面的0.1的指数位为-4,-4+1023 = 1019 转化为二进制就是:1111111011.

  所以,0.1表示为:

为什么0.1+0.2 ! == 0.3 7

  说了这么多,是时候该最开始的问题了,如何实现0.1+0.2=0.3呢?

  对于这个问题,一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3

为什么0.1+0.2 ! == 0.3 8

相关文章

敏捷开发和迭代式开发的根本区别是什么?

敏捷开发和迭代式开发的根本区别是什么?

2023-10-14
flutter和uni-app在应用层面有什么区别?

flutter和uni-app在应用层面有什么区别?

2023-10-14
Flutter和 qt的区别都有什么?

Flutter和 qt的区别都有什么?

2023-10-14
rnn和lstm中batchsize和timestep的区别是什么?

rnn和lstm中batchsize和timestep的区别是什么?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取