浮点数在内存中的存储方式(全网最详细,来来来!!!!)


各位博客朋友大家好,相信有很多小伙伴在刚接触数据类型的时候,都会纠结浮点数据是如何在内存中存储,现在我们一起去探讨这个问题?如果觉得有什么错误,欢迎各位小伙伴指出,好了,开始吧!!!

 

对于浮点类型数据,首先我们需要明白一点就是:浮点数和整数的编码方式是差异甚大的

是吗?我们举个例子

#include <stdio.h>

int main()

{

       int a = 9;

       float *pFloat = (float *)&a;

       printf("%f\n",*pFloat);

      

       float b = 9.0;

       float *p = &b;

       printf("%f\n",*p);

      

       return 0;

}

 

运行结果:

 

 

 

从以上结果得知浮点数的存储方式和整数是不一样的。

那么,浮点数据是如何存储的呢?

根据国际标准IEEE(电子与电气工程协会)规定,任何浮点数的二进制数存储都要遵循以下公式进行转换:

       NUM = (-1) ^ s * M * 2 ^ E

来来来我们解释一下:

       S : 当S为1时,表示为负浮点数,当S为0时,表示正浮点数

       M: 表示有效数 ,1<=M<2

      2^E: 表示指数

 

相信有同学看到上面的公式已经心情开始浮躁了,我自己当初也是和你们一样,心浮气躁,嗯,这不对的,这得改,所以同学们,我们要耐得住寂寞,让我们保持着

平静的心态继续往下探索吧!!!!

首先了解一下浮点在内存的存储方式,请看图~~

 

 

 

那问题来了,s表示符号位,0为正数,1为负数,那好办,这个位要么0,要么1,当然负数的存储方式是不一样的,我们本章节讨论的是正浮点的情况,浮点的存储方式,所以s为0

那e是什么呢?这八位存储的内容又是什么?

首先我们先确定e(指数域的二进制表示)是如何得来的,计算的e的结果需要用以下公式

e = E + Bias

E : 从上面公式知道E为指数

E的计算方式如下:

       我们以135.5这个浮点数为标本

    (1) 取整数135转换为二进制(不知道自己用计算器或者百度)为10000111

    (2) 取小数0.5转换为二进制(方法为小数乘2取整数,不懂百度)为 0.5 * 2 = 1.0,所以小数位1,

          举个例子:如果小数是0.375,计算方式为

            0.375 * 2 = 0.75         0

            0 . 75 * 2 = 1.5             1

            0.5 * 2 = 1.0                 1

            所以0.375转换为二进制数值为 0.011 就是 011

 

  (3)那么可以得出135.5的二进制为10000111.1

  (4)将这个数值套进公式

    10000111.1 = (-1)^0 * (1.00001111)*2 ^ 7

   所以得出E的值为7

 

Bias : 是一个等于2^k-1 – 1的偏置值(k为指数域位数,对于32位浮点数是8,对于64位浮点数而言是11,因为我的是32位系统,所以k值为8),通过此方法可以得出Bias的值为

2^8-1 – 1 = 127

 

那么e = 7+127 = 134 转换为二进制为 10000110

 

M : 小数部分 , 从上方可以得出结果为 00001111

 

好了,这样就可以将  s ,     e ,                      M

                                  0       10000110      00001111 000000000000000

共32位.

所以得出结果,135.5在内存中的存储方式如下

 0000 0000 低地址    0

1000 0000     -128(最高位1为负数)

0000 0111       7

0100 0011 高地址  67

                    

嗯,接下来验证奇迹的时刻来了,写个代码测试以下

 

#include <stdio.h>

 

int main()

{

       float m = 135.5;

       char *a = (char *)&m;

      

       printf("0x%p = %d\n",a,*a);

       printf("0x%p = %d\n",a+1,*(a+1));

       printf("0x%p = %d\n",a+2,*(a+2));

       printf("0x%p = %d\n",a+3,*(a+3));

      

       return 0;

}

 

运行结果如下

 

 

 

从结果可以得出我们的认证是正确的,哦,对了,还可以知道我这个系统是小端模式

 

最后附录自己分析的鬼画符~~~~~

 

 

 

 

 

本人 测试的操做系统为32位的ubuntu 14.04

 

好了这就是今天所有的内容,拜拜,有什么疑问或者建议的小朋友,记得请留言呦,让我们一起进步。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM