为什么0.1+0.2 != 0.3 ? 10进制和2进制的转换规则到底是什么?

98 阅读3分钟

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

控制台打印0.+0.2`,结果竟然不是0.3,为什么呢?

0.1 + 0.2 
0.30000000000000004

计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。

IEEE754标准 单精度(32位)/双精度(64位)浮点数解码

单精度(32位)浮点数的结构

image.png

双精度(64位)浮点数的结构:

image.png

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

十进制转二进制

整数

余数短除法除以二 : 除二取余,然后倒序排列,高位补零

image.png

活用这个方法可以将所有十进制数字转换成任何进制表达。除数为2是因为我们最终想得到的以2为基数的数(即二进制数值) 。如果最终想得到其他数系的数字,用目标数系的基数代替这个方法里二进制的基数2 就可以了。

降二次幂及减法混合运算

image.png

  1. 列表。 将以2为底数的幂函数以表格形式从右到左列出来。从20开始,20为1。指数加一递增。列表直至函数值最接近需要计算的十进制数字为止。比如说,我们现在要将十进制数字15610转换为二进制。
  2. 找出最合适的幂函数值。 找出小于且最接近需计算数字的幂函数值。在本例中,128是小于156的、以2为底数的幂函数值中最大的数值。所以在二进制列表128的下方写上1。然后用156减去128,得出28。
  3. 继续计算。 刚刚得出新得数28继续进行比较计算,看看哪一个幂函数值小于28。函数列表的下一个数字为64,64大于28,所以在64下方写上0。如此类推,看看那个数字小于28。
  4. 能减的数字记为1。 本例中,64和48都不能被28减,得出正数。16可以被28减,得出12。8也能被12减,得出正数,所以在16和8下方都写上1。现在的差为4。
  5. 继续减法运算,直到列表的最后。 记住在能被差减得出正数的数字下面记录为1,不能被减的数字下面记录为0。

image.png

image.png

负整数

  1. 正整数转成二进制

  2. 对二进制取反

  3. 取反后的二进制进行加1

image.png

小数

十进制的小数转换为二进制小数,主要是利用小数部分乘2,取整数部分,直至小数点后为0

image.png

0.1 + 0.2

image.png

0.1和0.2转成二进制都是无限循环的,超过了最大位数,所以存储时只能通过近似值去存储他们两,那自然的,当0.1 + 0.2时,近似值转十进制肯定也是近似值,所以造成误差,最大位数是根据硬盘内存大小决定的,所以一般硬盘内存越大,精确度越高。

image.png