Appearance
为什么0.1+0.2==0.3是false?为什么0.1+0.1==0.2是true?
简单来说就是,0.1和0.2的二进制是一个无限循环小数,而存储的时候不可能完整的存储,肯定会丢失精度。
至于为什么0.1+0.1等于0.2,我只能说算是巧合。
详细一点点来解释:
在数学上这肯定是true,所以说就涉及到js(其实不止js语言)底层是怎么保存0.1和0.2这个数字了。
回想一下在现实中你也没办法把 0.111111111...这个循环完整写出来,你只能写下1/9或者
而计算机中目前没有别的表达形式,除非用字符串来表达,但是字符串非常地慢!
这样想,如果底层是用字符串保存(也就是"0.1")那计算肯定是正确的。
但是用字符串来保存,那计算就是个大问题了,也就是计算"0.1"+"0.2"这个表达式在硬件(cpu)上面是没有提供的。
要做这个计算就只能在软件层(代码)实现,但是这样对于浮点数计算来说,速度是非常地慢,内存占用也高。
所以一般都不可能采用这种高精度的计算方式(不管什么语言都是),最终采用了IEEE-754双精度浮点数。
二进制的小数是怎么样的?
在没有小数的时候我相信很多人都懂,二进制的
所以我们可以按照这个规律来想,
按照上面这样二进制的小数就是0.1011100...这样的形式了,满足0和1组成。
那十进制的0.1转成二进制就是
二进制小数是怎么进位的?
很简单,只要是1就进位,下面举例
保留两位:0.1001 => 0.10
保留三位:0.1001 => 0.101、0.1011 => 0.110
IEEE-754双精度浮点数的格式是怎么样的?
一个有64个bit,0-51是小数部分共52位,52-62是指数部分共11位,63是标记位0表示正数1表示负数。
还有就是需要用科学计数法调整数字,也就是要改成
0.00011001100110011001100... = 1.1001100110011001100... *
- 首先因为是整数,所以符号位是0
- 然后整数部分的1是不存的,毕竟要求使用科学计数法,而二进制又只有0和1,那么默认所有IEEE-754的数都是有一个1开头的整数。
- 其次,不是直接将-4这个指数转成二进制保存到指数部分的,而是将e = n + 1023,计算之后得到的e转为二进制保存的,也就是
- 最后,从小数部位取出53位,然后进变成52位。
- 最终0.1的IEEE-754就是,
0 01111111011 1001100110011001100110011001100110011001100110011010