js 计算为什么0.1+0.2等于0.30000000000000004

js yekong 815℃

首先我们来看看一个浮点型数在计算机中的表示,它总共长度是64位,其中最高位为符号位,接下来的11位为指数位,最后的52位为小数位,即有效数字的部分。
· 第0位:符号位sign表示数的正负,0表示正数,1表示负数。
· 第1位到第11位:存储指数部分,用e表示。
· 第12位到第63位:存储小数部分(即有效数字),用f表示,如图1-1所示。
wanjunshijiecom20220517ObTHFL
因为浮点型数使用64位存储时,最多只能存储52位的小数位,对于一些存在无限循环的小数位浮点数,会截取前52位,从而丢失精度,所以会出现上面实例中的结果。

计算过程

接下来以0.1 + 0.2 = 0.30000000000000004的运算为例
首先将各个浮点数的小数位按照“乘2取整,顺序排列”的方法转换成二进制表示。
具体做法是用2乘以十进制小数,得到积,将积的整数部分取出;然后再用2乘以余下的小数部分,又得到一个积;再将积的整数部分取出,如此推进,直到积中的小数部分为零为止。
然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位,得到最终结果。
0.1转换为二进制表示的计算过程如下。

0.1 * 2 = 0.2 //取出整数部分0

0.2 * 2 = 0.4 //取出整数部分0

0.4 * 2 = 0.8 //取出整数部分0

0.8 * 2 = 1.6 //取出整数部分1

0.6 * 2 = 1.2 //取出整数部分1

0.2 * 2 = 0.4 //取出整数部分0

0.4 * 2 = 0.8 //取出整数部分0

0.8 * 2 = 1.6 //取出整数部分1

0.6 * 2 = 1.2 //取出整数部分1

1.2取出整数部分1后,剩余小数为0.2,与这一轮运算的第一位相同,表示这将是一个无限循环的计算过程。

0.2 * 2 = 0.4 //取出整数部分0

0.4 * 2 = 0.8 //取出整数部分0

0.8 * 2 = 1.6 //取出整数部分1

0.6 * 2 = 1.2 //取出整数部分1
...

因此0.1转换成二进制表示为0.0 0011 0011 0011 0011 0011 0011……(无限循环)。
同理对0.2进行二进制的转换,计算过程与上面类似,直接从0.2开始,相比于0.1,少了第一位的0,其余位数完全相同,结果为0.0011 0011 0011 0011 0011 0011……(无限循环)。
将0.1与0.2相加,然后转换成52位精度的浮点型表示。
0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 (0.1)

  • 0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 (0.2)
    = 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100
    得到的结果为0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100,转换成十进制值为0.30000000000000004。

笔记内容来自于书籍 JavaScrint 重难点实例精讲

喜欢 (0)