各位博客朋友大家好,相信有很多小伙伴在刚接触数据类型的时候,都会纠结浮点数据是如何在内存中存储,现在我们一起去探讨这个问题?如果觉得有什么错误,欢迎各位小伙伴指出,好了,开始吧!!!
对于浮点类型数据,首先我们需要明白一点就是:浮点数和整数的编码方式是差异甚大的
是吗?我们举个例子
#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
好了这就是今天所有的内容,拜拜,有什么疑问或者建议的小朋友,记得请留言呦,让我们一起进步。