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

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

文章目录

          • 一、例题


          • 二、浮点数在内存中存储方式

            • 2.1国际标准IEEE(电气和电子工程协会)754规定:
            • 2.2实际上,浮点数在内存的存储形式为:
            • 2.3具体M和E是怎么算的呢?

          • 三、题解

            • 3.1刚开始的例子答案
            • 3.2详细解析

          • 四、感谢与预告


一、例题

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

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详解;

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/584824.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存