C/C++ 中 float & double 类型数据在内存中的存储形式
IEEE 规定
IEEE 规定 float & double 类型的数据用三元组 {S, E, M} 表示,”S” 用 0 和 1 分别表示正数和负数,尾数 “M” 用原码表示,阶码 “E” 用移码表示,还规定尾数域的最高有效位总是 1,并且最高位不予存储(都是 1 也就不用浪费存储空间了)
float 类型
单精度浮点数 float(32bit) 表示为:
SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
-
符号位(S)1 bit;
-
阶码(E)8 bit,阶码的偏移量为 127(7FH);
-
尾数(M)23 bit,用小数表示,小数点放在尾数域的最前面;
所以 32bit 的单精度浮点数可表示为:
\[float = (-1)^{S} * (1.M) * 2^{(E - 127)}\]double 类型
双精度浮点数 double(64bit) 表示为:
SEEE EEEE EEEE MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM
-
符号位(S)1 bit;
-
阶码(E)11 bit,阶码的偏移量为 1023(3FFH);
-
尾数(M)52 bit,用小数表示,小数点放在尾数域的最前面;
所以 64bit 的双精度浮点数可表示为:
\[double = (-1)^{S} * (1.M) * 2^{(E - 1023)}\]注意
-
当一个浮点数的尾数为 0,不论其阶码为何值,或者当阶码的值遇到比他能表示的最小值还小时,不管其尾数为何值,计算机都把该浮点数看成零值,称为机器零;
-
当阶码 E 为全 0 且尾数 M 也为全 0 时,表示的真值为零,结合符号位 S 为 0 或 1,有正零和负零之分;
-
当阶码 E 为全 1 且尾数 M 也为全 0 时,表示的真值为无穷大,结合符号位 S 为 0 或 1,有正无穷和负无穷之分,故在 32 bit 浮点数表示中,要去除 E 用全 0 和全 1(255) 表示零和无穷大的特殊情况,因此,阶码 E 的取值范围变为 1~254,指数的偏移量不选 128(1000 0000B),而选 127(0111 1111B),对于 32 bit 表示的浮点数,真正的指数值 e 为 -126 ~ +127,因此 32 bit 浮点数的范围为 $2^{-126}$ ~ $2^{127}$ 约等于 $10^{-38}$ ~ $10^{38}$ 次方,64 bit 浮点数 double 与 32 bit 浮点数 float 推导方法相似。