掘金搬来思否
浮点数的存储格式:IEEE754-64bit
64位组成格式为:S(1位符号位) E(11位阶码)M(52位尾数)
- 符号位:决定正负,0位正,1位负
- 阶码:指数位则为阶码-1023,决定了数值的大小
- 尾数:有效数字,决定了精度
- 用科学计数法格式则为:(-1^(符号位0/1)) 1.xxxxx(尾数位) 2^(指数位)
须要记住的IEEE754规范有:
- 尾数位:有效数字的第一位一定是1,因此这个1不会被储存,也就是说实际上尾数位52+1,相似1.xxx第一位就是1。
- 阶码:不存在负值,那怎么表示负指数呢?就是减去一个固定值;其值就是1023,也就是偏移量1023;除去全是1和全是0的状况,那么指数位的范围则是[(1-1023),(2046-1023)] == [-1022,1023]。
- 当阶码全位0,尾数全为0时,采起非规格化,二者不包含隐含的1,用来表示0。
- 最简单的精度算法就是:2^53是16位十进制,因此15位确定能精确处理。
- 固然还有不少,有兴趣能够自行查阅一下。
知道了这些,就能更好的理解一些数值的由来:
Number.MAX_VALUE = 1.7976931348623157e+308;
尾数:1.xxx1,后面为52个1,
要获得最大值,咱们就须要把小数点日后移,就靠指数1023-52,剩余971;
所以最大值等价于((Math.pow(2,53)-1)*Math.pow(2,971))
Number.MIN_VALUE =5e-324;
尾数:1.xxxx1,后面第52位为1,其他为0,这时首位的1须要隐藏,
这时候就是负了52位,在加上2^-1022,
等价于((Math.pow(2,-52))*Math.pow(2,-1022))
Number.MAX_SAFE_INTEGER = 9007199254740991;
安全数就是可以精确处理的,精度靠尾数决定,
那咱们来看当1.1111...1,小数点后接52个1,这是精度最大显示,
要取其最大值那就是向指数借52位,因此最大安全数就等于Math.pow(2,53)-1
同理Number.MIN_SAFE_INTEGER = -9007199254740991;
对最大安全数添加负号便可
重点0.1 + 0.2 怎么计算的呢?
首先,0.1转二进制 :0.0 001100110011001100110011..0011 0011,
改写为科学计数法表示:1.100110011...0011(0011)*2^-4,
尾数位为52为须要取舍括号中最后一位舍去进1,指数为-4,那个阶码就是-4+1023=1019,
最终浮点数格式:
0-01111111011-1001100110011001100110011001100110011001100110011010
同理0.2能够表示为:
0-01111111100-1001100110011001100110011001100110011001100110011010
最后二者相加结果为:
0-01111111101-0011001100110011001100110011001100110011001100110100,
指数位为-2,
1.00110011001100110011001100110011001100110011001101(00)*2^-2
因此二进制表示:
0.0100110011001100110011001100110011001100110011001101(00),
那么转为十进制就是0.1 + 0.2 = 0.30000000000000004 != 0.3