3. 浮点型在内存中的存储
(一). 字面(直接写出来的)浮点数:
3.14159
1E10 --> 1.0 * 10^10 (1.0 乘 10的10次方) --> E:底数是10
(二). 浮点数类型:
浮点数:数据乘以相关权重后,小数点位置可以浮动的
float -- 单精度浮点数 -- 4字节
double -- 双精度浮点数 -- 8字节
long double -- 更长的双精度浮点数 -- 8字节
(可在 float.h头文件 查看该类型范围等信息)
(三). 浮点数存储的例子:
在内存中存储数据的时候,
以 %f 浮点数的形式获取数据
和
以 %d 整数的形式获取数据
是不一样的
#include <stdio.h> int main() { int n = 9;//4字节 float* pFloat = (float*)&n; //把 n 的地址强制转换为 float类型 赋给指针变量 pFloat printf("n的值为:%d\n", n); //使用 %d 打印 n printf("*pFloat的值为:%f\n", *pFloat); //使用 %f 打印 地址中的内容 *pFloat = 9.0; //使用指针变量把 9.0 赋给 n的空间 printf("num的值为:%d\n", n); //使用 %d 打印 赋值后的 n printf("*pFloat的值为:%f\n", *pFloat); //使用 %f 打印 赋值后的 地址中的内容 return 0; }
说明 浮点数 和 整型 在内存中存储 和 获取 的形式是不一样的(存储方式有差异)
(以 整型 存储,可以用 整型 获取,但不能用 浮点数类型获取)
(四). 浮点数存储规则
浮点数在计算机内部的表示方法
根据 国际标准IEEE(电气和电子工程协会)754 ,
任意一个 二进制浮点数V 可以表示成下面的形式:
(-1) ^ S * M * 2 ^ E
- (-1) ^ S 表示 符号位,当 S=0, V为正数;当 S=1, V为负数。
(任何数的0次方都等于 1,-1的1次方等于 -1)
- M 表示 有效数字,大于等于 1,小于 2。
(这里 V 是二进制浮点数,所以这里 1 <= M < 2 )
2 ^ E 表示 指数位 。 (几进制 这里就是 几^E,这里 V 是二进制浮点数,所以是 2^E,
“小数点移了几位”,这里的 E 就是 几 )
例子:
(五). IEEE 754 规定的 浮点数存储模型:
float -- 单精度浮点数存储模型:
对于32位的浮点数(float),
最高的1位是 符号位S ,
接着的8位是 指数E ,
剩下的23位是 有效数字M 。
double -- 双精度浮点数存储模型:
对于64位的浮点数(double ),
最高的1位是 符号位S ,
接着的11位是 指数E ,
剩下的52位是 有效数字M 。
(六). IEEE 754 对 有效数字M 和 指数E 的特别规定:
有效数字M:
前面说过,1<=M<2,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。
有效数字M的保存:
IEEE 754 规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的 xxxxxx 部分。
后面的 xxxxxx 部分。
(小数点前面不存,只存小数点后面)
有效数字M的读取:
比如保存 1.01 时,只保存 01 ,等到读取的时候,再把第一位的1加上去。这样做的目的,是为了节省1位有效数字。
以 32位浮点数 为例,留给 M只有23位,将第一位的1舍去以后,等于可以保存 24位有效数字。
(可以使保存的小数精度再高一点)
指数E(比较复杂):
(1). 指数E 在内存中的存储:E 为一个 无符号整数(unsigned int)
这意味着,如果 E 为8位,它的取值范围为 0~255;如果 E 为11位,它的取值范围为 0~2047。
但是,科学计数法中的 E 是可以出现负数的,所以 IEEE 754 规定,存入内存时 E 的真实值必须再加上一个中间数(可以把E修正为正数),对于8位(float)的 E ,这个中间数是 127;对于11位的 E(double),这个中间数是1023。
比如,2^10的 E 是10,所以保存成 32位浮点数 时,必须保存成 10+127=137,即10001001。
(符号位S、有效数字M 和 指数E 例子:)
(计算符号位S:S为0,符号为正;S为1,符号为负
计算指数E:移动位数 + 中间值
计算有效数字M:小数点后的数,再用0补齐剩余位数)
(2). 取出内存中的 指数E(三种情况):E不全为0或不全为1
这时,浮点数 就采用下面的规则表示:
即 指数E 的 计算值 减去中间值127(或1023),得到真实值(存储时是真实值+中间值),再在 有效数字M 前加上第一位的1
(存储时把第一位的1舍去了,其实就是按存储的相反形式取出,怎么放进去怎么取出来)。
(3). 取出内存中的 指数E(三种情况):E全为0
指数E 是通过 真实值+中间值 算出来的,如果E全是0,(32位系统)说明E的真实值是 -127,
指数是-127说明这个值是非常小的。
这时,直接规定浮点数的 指数E 等于 1-127(或者 1-1023 ),即为真实值。
有效数字M不再加上第一位的1,而是还原为 0.xxxxxx 的小数。
这样做是为了表示 ±0 ,以及 接近于0 的很小的数字。