【C语言进阶】③探究浮点数在内存中的存储方式

一、例题

想想看,输出的结果是什么?

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; }
二、浮点数在内存中存储方式
2.1国际标准IEEE(电气和电子工程协会)754规定:
  1. IEEE二进制浮点数算术标准(IEEE 754):是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。
  2. IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。
  • 以上内容来自于百度百科。
  • 简单点来说:一个任意的二进制浮点数A可以表示成下面的形式:
  1. (-1)^S * M * 2^E
    2.s=(-1)^S,s表示的是符号位,当s=0时,A为正数;当s=1时,A为负数;
  2. M表示有效数字,1 <= M < 2;
  3. 2^E表示指数位;

举个例子:

  • 十进制的11.0,写成二进制为:1011.0,相当于1.011x2^3;
  • 那么按照上面的形式:s=0,M=1.011,E=3;
  • 而十进制的-11.0,写出二进制为:-1011.0,相当于-1.011x2^3;此时,s=1,M=1.011,E=3;
2.2实际上,浮点数在内存的存储形式为:
  • IEEE 754规定:
    对于32位的单精度浮点数而言,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
  • 即:
    在这里插入图片描述
2.3具体M和E是怎么算的呢?

实际上:

  • 前面说过,1<= M < 2,也就是说,M可以写成:1.xxxx的形式,其中xxxx表示小数部分。
    IEEE754规定:计算机内部保存M时,默认这个数的第一位是1,因此可以被舍去,只保留后面的小数部分;比如对二进制1.011来说,只保存.011,等到读取是,再在小数点前加1;这样做的目的是节省了1位有效数字。以单精度浮点数(32bit)来说,留给M的只有23位,将第一位1舍去后,等于可以保存24位有效数字;

  • 对于指数E
    (1)E作为一个无符号整数,这意味着,如果E为8位(单精度浮点数),它的取值范围为:0-255;如果E为11位(双精度浮点数),它的取值为:0-2047;
    (2)但是,科学记数法中,指数位是可以为负数的,所以**IEEE 754规定:E存入内存时,必须在加上一个中间数,对于单精度浮点数来说,这个数是127,对于双精度浮点数来说,这个数是1023;
    例如:2^10,E为10,保存在内存中时为:10+127=137,即写成二进制为:1000 1001;

  • 然后指数E从内存中取出还可以分为三种情况:

    1.E不全为0或者全为1:

    这时,浮点数就采用下面规则表示,即指数E的计算值减去127(或者1023)得到真实值,在将真实值得有效数字M前加上第一位1,即得到二进制数;
    例如:
    十进制:0.5(1/2) 的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移动1位,为:1.0*2^(-1),其E为:-1+127=126,表示为:0111 1110,而M为:1.0去掉整数部分1,为0,补齐到23位为:00000000000000000000000;
    则这个数的二进制在内存中保存形式为:
    0 0111110 0000000000000000000000

2. E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,
有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于
0的很小的数字。

3. E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

三、题解
3.1刚开始的例子答案

在这里插入图片描述

3.2详细解析
  1. n的值为:9;
    解:n=9为int类型, float* pFloat = (float*)&n;的含义是使用float类型指针pFloat指向n的地址并把n的地址强制转换为float*,此时,n的值并没有改变,只是加了一个指针指向它,所以接下来以整型打印整型9;
  2. *pFloat的值为0.000000;
    解:
    (1)整型9的在内存的表示形式为:00000000 00000000 00000000 00001001
    (2)而计算机以浮点数来读取整型时,会把首位0看成s,后面8位0会看成E的值,最后23位00000000000000000001001 看成有效值M;
    (3)那么这就符合E的取值全为0这种情况,此时有效值非常接近0;所以打印为浮点型0.000000;
  3. num 的值为::1091567616;
    解:
    (1)此时n的值已经被指针*pFloat修改为浮点型:9.0;
    (2)浮点型9.0形式为:(-1^0 * 1.001 * 2^3
    (3)s=0 ; E 等于3 +127 = 130 ; M = 1.001 ,有效值为001;
    (4)9.0在内存的存储形式为:0 1000 0010 001 00000000000000000000
    (5)而以整型%d的形式打印此时的浮点型,就得:
    在这里插入图片描述
  1. *pFloat的值为9.000000;
    解:
    此时就很简单了,因为n的值已经被指针修改为浮点型9.0,那么此时以浮点型%f来打印浮点型9.0,得到的值当然为9.000000;
四、感谢与预告
  1. 如果本文对你有所帮助,麻烦你点个赞加收藏,你的支持就是小编更新的最大动力,非常感谢!
  2. 预告下一篇文章:⑤指针的归纳and详解;
  • 17
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白杨Cc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值