依然是基础:
IEEE 754 64位浮点数存储格式解析
s代表 符号位 1位;
e代表指数位 11位;它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
f代表有效数值 52位,大于等于1,小于2,因为f总是1.XXXXXX,所以存储的时候将1省略掉,
怎么存储呢?
a = 12.5
符号位s:a>0;s为0;用二进制表示为0
指数位e:
a表示为二进制为: 1100.0 指数为3;
Exponent 为 1026 (1023 + 3),用二进制表示为: 10000000010
有效数值
有效数字需要去掉最高位隐含的1,则有效数字的整数部分为 : 100
将十进制的小数转换为二进制的小数 0.5转成二进制为0.1,则12.5转成二进制为1001
后面补0,则a的二进制可表示为:
0 10000000010 1001000000000000000000000000000000000000000000000000
转换回来:
-
Sign = bin(0) = 0
-
Exponent = bin(10000000010) = 1026
-
Fraction = bin(0.1001) = 2 ** (-1) + 2 ** (-4) = 0.5625
真值:
(-1) **0 * 2 **(1026-1023) * (1 + 0.5625) = 12.5
为什么指数位把1023作为中间数?
指数位有11位,可以表示2048个数,既要表示正数和负数,(有两种办法,首位0和1代表正负,或者取中间数小于这个中间数的为负数,我看到有一种解释,首位设置为正负的时候,130代表-30,机器会认为130(-30)大于30,这个不合理。所以设置中间数,)
但是,2048这个数IEEE 754有其他用途:
NaN
(指数位全是1,有效数值位不为0)
正负无穷大
(指数位全是1,有效数值位全为0)。
0这个数也有其他用途:
数值0
指数位为0,有效数值位为0
表示一个极小的正数:0.00......0001*2**(2022)
指数位为0,有效数值位不为0代表指数为0,有效位数不用+1
少了2个数字,只好用1023做中间数了。
双精度浮点数取值范围:
这个是在吃饭的时候突然理解的,虽然双精度浮点数可以表示近乎于(2**1024)*2的数。但是,超越一定范围之后,有些数存储不了;
我举一个简化的例子:(双精度浮点数有效位数为52,这里方面举例假设它有效位数为2)
1.00*2**(1023-1023)=1;
1.00*2**(1024-1023)=2;
1.10*2**(1024-1023)=3;
。。。。。
1*2**3=8;
1.01*2**3=10;(都是二进制计算)
那么中间的9表示不了。
所以对于双精度浮点数,能精准表示的最大整数是小于 Math.pow(2, 53),十进制即 9007199254740992。再大的话,就会出现有的值存储不了的情形。
JavaScript 能够准确表示的整数范围在-2^53
到2^53
之间(不含两个端点)
float 类型(即 IEEE754 单精度浮点数格式32位)能表示的最大整数:
0 00000000 00000000000000000000000
指数位最大的值:((2**8)-1-1-127)=127(全是1的值有其他用途,上面有解释;)
有效数值最大的值:1.11111111。。。。。11(有23个小数位)
那么综合起来:1.11111111111111111111111*2^127=(2-2^-23)*2^127=2^128-2^104