不知道大家在写C语言的时候有没有好奇过,浮点型的数据在内存中是如何存储的呢?
我们可能只知道在32位平台下,float类型占四个字节,double类型占八个字节,像下图一样。
浮点数是怎么存放的呢?
相比于整型和字符型而言,浮点型的存储要复杂一点。
对于浮点型的存储标准,根据国际标准IEEE(电气电子工程师学会)754的定义:
任何一个浮点数都可以写成 (-1)^S*M*2^E其中
- (-1)^S表示符号位,S=0 为正数 ,S=1 为负数;
- M表示有效的数字,1 <= M < 2;
- 2^E表示指数位
看不懂没关系,举个例子:
- 5.0 = 101.0 = 1.01*2^2
5.0这个浮点数写成二进制的形式是 101.0 再将 101.0 转换成科学计数法 就是 1.01*2^2
而它又是一个正数 所以 它的 S=0,M=1.01,E=2。
- 9.5 = 1001.1 = 1.0011*2^3
9.5这个浮点数写成二进制的形式是 1001.1 再将 1001.1 转换成科学计数法 就是 1.0011*2^3
而它又是一个正数 所以 它的 S=0,M=1.0011,E=3(注意十进制小数和二进制小数的转换)
变成这个样子以后,IEEE754规定:
- 对于32位浮点数(float)S占1位,E占8位,M占23位
- 对于64位浮点数(double)S占1位,E占11位,M占52位
此外IEEE754还做了一些规定:
- 对于M:因为永远是 1 <= M < 2的 因此再保存的时候,只需要保存小数点后面的小数部分就可以了,最后取出来的时候再加上1。
- 对于E:情况比较复杂。IEEE754规定E是一个无符号的整数,因此在E是8位时范围是。0~255,11位时的范围是0~2047,但是实际情况中的E是会出现负数的。所以还需要对E进行修正。对于8位的E 需要 加上 127 再存储;对于11位的E 需要 加上 1023再存储。
- 例如 5.5 的 S=0,M=1.011,E=2,M 只取小数点后的数就是011,E=2+127=129 的二进制就是10000001,因此5.5写入内存就是 0 10000001 01100000000000000000000。
浮点数怎么取出来呢?
分为三种情况:
E不是全0也不是全1:那就用 E-127(或1023),然后M+1 再按公式拼出原数。
E为全0:这时的E直接就等于1-127(或1-1023),M也不再加1,直接还原成0.xxxx的数表示一个特别接近与0的数。一个数加127为全0,那么E最大也是-127,而(-1)^S*M*2^-127无限接近0。
E为全1:表示一个特别特别大的数。这个也好理解,当一个数加127为全1 那么这个E至少是128,而(-1)^S*M*2^128已经非常大了。
以上就是浮点数在内存中的存取过程。
实践一下:
看看下面代码的结果是什么呢
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n=%d\n", n);
printf("*pFloat=%f\n", *pFloat);
*pFloat = 9.0;
printf("n=%d\n", n);
printf("* pFloat=%f", *pFloat);
return 0;
}
解析:
9 在计算机内存储的是 0000 0000 0000 0000 0000 0000 0000 1001;用浮点数的指针指向时就会把它解析成 0 00000000 00000000000000000001001
此时的S=0;E是00000000 直接等于1-127=-126 而M也不再加1 直接是0.00000000000000000001001根据公式就等于 +0.00000000000000000001001*2^-126
打印时,printf("n=%d\n", n):就是以整型打印,所以答案就是9;printf("*pFloat=%f\n", *pFloat):是按浮点型打印,所以结果是+0.00000000000000000001001*2^-126 近乎就是0了。
*pFloat = 9.0,相当于以浮点型的形式存储 9.0=1001.0=1.001*2^3
那么就有S=0,E=3+127=130 也就是 10000010,M=00100000000000000000000 合起来就是01000001000100000000000000000000
修改后打印时,printf("n=%d\n", n):以整数形式打印01000001000100000000000000000000这段二进制数字就是1091567616;用计算器验证一下:
而printf("* pFloat=%f", *pFloat):以浮点数形式打印就是浮点数本身。
所以: