本文重点谈论浮点数在内存中是如何存储的。
示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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;
}
Q:请问结果是什么?
要想解决这道题,浮点数的存储规则必须了解
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
1️⃣(-1)^S * M * 2^
2️⃣-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
3️⃣M表示有效数字,大于等于1,小于2
4️⃣2^E表示指数位。
以5.5为例:
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M |
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M |
IEEE 754对有效数字M和指数E,还有一些特别规定。
1.M的取值范围:[1,2),IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去。
2.E是无符号整数,为防止E是负数。当E是8位,E+127;
当E是11位,E+1023
3. 一般情况下E不全为1或不全为0:
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值 再将 有效数字M前加上第一位的1 |
4.E为全0:(以32位平台下为例)
E为全0,在内存中就是
这时E= 0-127 = -127,还原为真实值为(-1)^S *1.XXXX... *2^(-127);但是规定不将M加上有效数字1,改为:(-1) ^S *0.XXXX... *2 ^(-126) .这是一个无限接近于0的数 |
5.E为全1:(以32位下平台为例)
E在内存中就是:
所以E = 255-127=128,那么还原为真实值就是:(-1)^S*1.XXXXXX... *2 ^128 这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);反正就是这个数足够大。 |
接下来就让我们解决一下5.5是怎么存入内存的
以16进制表示就是
这是小端存储,接下来我将谈一谈这个大小端存储规则。
大小端存储方式
1.如何理解大小端:
举一个例子就可以说明,比如吃鸡蛋,是先敲大头,还是先敲小头呢,所有人无法达成一致,因为双方都没有足够的理由去说服对方。大小端也是这样的。
2.大小端的基本概念:
3.大小端是如何影响数据存储的?
答:大小端存储方案,本质数据和空间按照字节为单位的一种映射关系。
无论采用大端还是小端,都不影响用户的使用。
解决开始的示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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;
}
首先
int n = 9
2.
*pFloat = 9.0
1.
2.
显然结果是:9.000000,将浮点数存入,再用浮点数的方式打印。