系统相关
首页 > 系统相关> > 深度刨析数据在内存中的存储(二)

深度刨析数据在内存中的存储(二)

作者:互联网

前面已经写了整数在内存中的存储,以及大端机和小端机的概念,以及相应的练习,详见深度刨析数据在内存中的存储(一),这次就写写浮点数在内存中的存储。

浮点数在内存中的存储

上一节也提过常见的浮点数有float和double类型,其实还有long double型,但是平时不常见该类型。
话不多说,那么,浮点数和整数一样,在计算机中,都是以二进制代码存储在计算机内存中,对于整数而言,就是按正常的将对应的十进制转化为二进制,然后从计算机的低位开始存储(对于小端机而言),符号位放在最高位。但对于浮点数而言,它有自己对应的存储方式。
根据国际标准IEEE(电气和电子工程师协会)754,任意一个二进制浮点数可以表示成一下的格式:

(-1)^S * M * 2^E

• (-1)^S 表示符号位,当 S=0 时,表示该浮点数为正数,当 S=1 时,表示该浮点数为负数。
• M 表示该浮点数的有效数字,1 <= M < 2。例如:987 = 9.87 * 10^2,其中9.87就为有效数字。
• 2^E 该浮点数的指数位。相当于科学计数法中的指数位

以上只是规定了二进制的浮点数应该表示的格式,那么对于二进制的存储方式,IEEE754是这样规定的:
对于32位的浮点数,最高的一位(最高位)是符号位S,接着的8位是指数E,剩下的23位为有效数字M,32位的浮点数为单精度浮点数存储模型。
在这里插入图片描述
对于64位的浮点数,最高的一位(最高位)是符号位S,接着的11位是指数E,剩下的52位为有效数字M,64位的浮点数为双精度浮点数存储模型。
在这里插入图片描述
这里需要注意的一点是E,是一个无符号的整数(unsigned int),这就意味着,E若为8位,它的取值范围位0-255,若为11位,它的取值范围为0-2047。但是,对于科学计数法而言,E是可以出现负数的,因此IEEE754规定,存入E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127,对于11位的E,它的中间值为1023。即指数E的计算值减去127(或1023),就可以得到真实值。注:这里的计算值是已经规范化后的E,而真实值是最初的那个未被规范的E值,即E(真) + 127 = E(计)。
IEEE754还规定了,在计算机内部保存M时,默认的这个数的第一位是1,因此在保存时只保留小数部分的二进制代码。这样做的目的就是可以节省一位有效数字。
对于E还有两种特殊的情况:
E全为0:(指的是二进制代码-- 0000,0000)

当E全为0时,0-127=-127,即就是2^(-127)(或更小),-127(或更小)为真实值,因此还原为小数之后,是一个非常接近0的的数字。

E全为1:(1111,1111)

当E全为1时,255-127=128,128为真实值,即为2^(128),当还原为小数之后,表示一个无穷大的数(正负取决于S,而不是E)

举个例子:将10.25转化为二进制浮点数。

10.25
1.转化为二进制---> 1010.01
2.转化为IEEE754单精度模型。----->(-1)^S*M* 2^E
则其中 S = 0,M = 1.01001,E = 3(E为真实值)
3.规范E的数值,将其变为计算值 ---->3+127=130
则E(计)=130,对应二进制代码为1000,0011
因此,最终结果为:0 1000,0011 01001000000000000000000

即:
在这里插入图片描述
练习:

int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 printf("n的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 *pFloat = 9.0;
 printf("num的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat); 
 return 0;
 }

分析:首先对于 float *pFloat = (float *) &n; 这行代码进行"翻译";存储n的地址为int类型,创建一个float类型的指针的空间,使该指针指向被强制转化为float类型的存储n的地址。因此最终的结果为n在内存中的内容不变,但是对应得存储方式发生了改变,由一个整型(整数)变成了一个实型(浮点数)。

n 在整数内存中二进制表示为:0000,0000 0000,0000 0000,0000 0000,1001
但当对n的地址进行强制转化为float类型后,其内容不变,但是对应的存储方式发生了改变。
对其按二进制浮点数格式还原可得 (-1)^0 * 0.000....0001001(中间19个0) * 2^(-127)(或更小),E是全为0的情况。
因此,对*pFloat打印的结果为0.00000000,因为数值太小,计算机不能精确的存储该数值,因此打印结果为0.00000000.

结果截图为:
在这里插入图片描述
当进行到*pFloat = 9.0 语句之后,是对pFloat所指向的n的内存空间进行修改,将其改为9.0,表示浮点数格式为:-1^0 1.001 2^3,则表示为 在内存中的二进制为:0 1000,0010 00100000000000000000000,若转为int类型输出后,其对应的值就为图中显示的数值,即1091567616。

标签:存储,0000,二进制,刨析,内存,127,pFloat,浮点数
来源: https://blog.csdn.net/weixin_43937101/article/details/111586374