您现在的位置是:首页 >其他 >C语言之浮点型在内存中的存储网站首页其他
C语言之浮点型在内存中的存储
?博主CSDN主页:Wsys1mple?
?分类专栏:C语言初阶?
?gitee代码仓库:Wsys1mple的代码仓库?
?关注我,持续更新更多学习分享?
目录
1. 前言?
这里我们将深度剖析浮点型在内存中的存储,希望我的文章对你有所帮助。
常见的浮点数:
3.1415926
2E10(2乘以10的10次方)
浮点数家族包括:float、double、long double 类型。
其中浮点数的表示范围在 float.h 文件中定义
2. 浮点数存储和整形存储的区别?
我们先看一个浮点数存储的例子:
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d
", n);//9
printf("*pFloat的值为:%f
", *pFloat);//0.000000
*pFloat = 9.0;
printf("num的值为:%d
", n);//1091567616
printf("*pFliat的值为:%f
", *pFloat);//9.000000
return 0;
}
输出的结果:
为什么是这样呢?num 和 *float 在内存中明明是同一个数,而实际的结果是 *pfloat 的值变成了0.000000,num 的值变成了一个特别大的值,似乎并不符合常理。
我们带着疑问,继续学习以下内容。
3. 浮点数存储规则?
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
- (-1)^S * M * 2^E
- (-1)^S表示符号位,当S=0时,V为正数;当S=1时,V是负数。
- M表示有效数字,并且取值范围是大于等于1,小于2。
- 2^E表示指数位
举例来说:
十进制的 5.0,写成二进制是 101.0,相当于 1.01 * 2^2。
按照上面的格式,可以得到 S=1,M=1.01,,E=2。
同理,十进制的 -5.0,写成二进制是 -101.0,相当于 -1.01 * 2^2。
按照上面的格式,可以得到 S=0,M=1.01,E=2。
IEEE 754规定:
对于32位的浮点数,最高位是符号位S,接着的8位是指数E,剩下的23位是有效数字M。
对于64位的浮点数,最高位是符号位S,接着的11位是指数E,剩下的52位是有效数字M。
注意:对于所有的浮点数,都可以用 S,E,M表示,因此在内存中存储S,E,M相当于存储了浮点数。
4. IEEE 754对M的特别规定?
前面提到有效数字 M 的取值范围是大于等于1,小于2,也就是说 M 可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的小数部分。
举例来说:
保存1.01时,只保存01,等到读取的时候,再把首位的1加上去。
这样的目的是节省1位有效数字。以32位浮点数为例,M有23位,将首位的1舍去以后,等于可以存储24位有效数字。
5. IEEE 754对E的特别规定?
首先,E为一个无符号整数 (unsigned int)
E如果是8位,取值范围为0~255;E如果是11位,取值范围为0~2047。但是科学计数法中的E可以出现负数(指数出现负数),所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数
对于8位的E,这个中间数是127(例如E为-127,加上中间数127后值为0,这样才符合无符号整数的取值范围),对于11位的E,这个中间数是1023。
举例来说:
2^10的E是10,在保存成32位浮点数时,必须保存成10+127=137,即10001001。
6. 指数E从内存中取出的三种情况?
6.1 E不全为0或不全为1✨
指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
举例来说:
0.5的二进制形式为0.1,由于规定正数部分必须为1,所以将小数点向右移1位,则为
1.0 * 2^(-1) ,阶码()为-1+127=126,表示为01111110,尾数1.0去掉整数部分为0,二进制表示形式为:
0 01111110 000000000000000000000
(阶码:对于任意一个二进制数N,可用N=S×2^P表示,其中S为尾数,P为阶码,2为阶码的底,P、S都用二进制数表示,S表示N的全部有效数字,P指明小数点的位置。 当阶码为固定值时,数的这种表示法称为定点表示,这样的数称为“ 定点数 ”;当阶码为可变时,数的这种表示法称为 浮点 表示,这样的数称为“ 浮点数 ”。
阶码:在机器中表示一个浮点数时需要给出指数,这个指数用整数形式表示,这个整数叫做阶码。)
6.2 E全为0✨
这时,指数E等于1-127(即-126) (或者1-1023(即-1022))即为真实值,有效数字M不再加上第一位的1,而是还原为0,xxxxxx的小数,这样做是为了表示±0,以及接近于0的很小的数字。
6.3 E全为1✨
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。
7. 解释浮点数存储的例子?
int main()
{
int n = 9;
//0 00000000 00000000000000000001001
//S E M
//E全为0时,浮点数的指数等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数
//即S=0 E=-126 M=0.00000000000000000001001
//则为(-1)^0 * 0.00000000000000000001001 * 2^-126
float* pFloat = (float*)&n;
printf("n的值为:%d
", n);//9
printf("*pFloat的值为:%f
", *pFloat);//0.000000
*pFloat = 9.0;
//1001.0
//(-1)^0 * 1.001 * 2^3
//得到S=0 E=3 M=1.001
//存的时候E加上中间数127为130
//则二进制表示形式为0 10000010 00100000000000000000000
printf("num的值为:%d
", n);//1091567616
printf("*pFliat的值为:%f
", *pFloat);//9.000000
return 0;
}
8. 总结?
对于浮点型在内存中的存储,做到知道是怎么存的就足够了,不用死记硬背。