前言大家好呀!👋这个是付青云同学的博客,是一名大一在校生哦!😁😁
目前一直在学习C语言。🐸
写博客是为了来记录我的学习过程,同时也希望通过博客能够帮助到需要帮助的人。
如果我的博客可以帮助到你,不妨给我一个关注哦😁
最近发现一个这样的代码:
int main()
{
int i = 5;
float* pi = (float*)&i;
printf("i=%d\n", i);
printf("pi=%f\n", *pi);
*pi = 5.0;
printf("i=%d\n", i);
printf("pi=%f\n", *pi);
return;
}
它运行之后的结果是这样的?
就感觉挺有意思的,但为什么会这样却并不清楚,于是查了一些资料,发现关于浮点型类型的数据在内存中的储存大有文章,因此写下了这个博客。
本人是C语言的初学者,文章若有纰漏或错误部分,还敬请指出,不胜感谢!
浮点型类型的数据在内存中的储存 关于浮点型数据常见的浮点数:
浮点型类型的数据在内存中的储存规则3.14159
1E10
浮点数包括float、double、long double类型等
回到前言中那个题目
int main()
{
int i = 5;
float* pi = (float*)&i;
printf("i=%d\n", i);
printf("pi=%f\n", *pi);
*pi = 5.0;
printf("i=%d\n", i);
printf("pi=%f\n", *pi);
return;
}
i和pi在内存中明明是同一个数,为啥么浮点数和整数的解读结果会差别这么大?
关于这个,我查阅了相关资料:
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:
- (-1)^S * M * 2^E
- (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
- M表示有效数字,大于等于1,小于2。
- 2^E表示指数位。
就就比如刚刚的pi=5.0:
- 十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
按照上面V的格式,可以得出s=0,M=1.01,E=2。 - 十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。
按照上面V的格式,可以得出s=1,M=1.01,E=2。
对于32位浮点数:
最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
对于64位数据:
最高的1位是符号位s,接着的11位是指数E,剩下的52位为有效数字M。
IEEE 754对有效数字M和指数E,还有一些特别规定:
前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的
xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
至于指数E,情况就比较复杂:
首先,E为一个无符号整数(unsigned int)。这意味着:如果E为8位,它的取值范围为0 ~ 255;如果E为11位,它的取值范围为0~2047。
但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
具体可见维基百科:IEEE_754
知道了这些知识之后,我们就可以解上面的那道题了
- 为什么0x00000005还原成浮点数,就成了0.000000 ?
首先,将 0x00000005 拆分,得到第一位符号位s=0,后面8位的指数 E=00000000 ,最后23位的有效数字M=000 0000 0000 0000 0000 0101。
5 -> 0000 0000 0000 0000 0000 0000 0000 0101
因此,浮点数V就写成了:
V=(-1)0 × 0.00000000000000000000101×2(-126)=1.01×2(-147)
显然:V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000
- 浮点数5.0,如何用二进制表示?还原成十进制又是多少?
浮点数5.0等于二进制的0101.0,即1.01×22
5.0 -> 101.0 -> (-1)0×1.01×22 -> s=0, M=1.01,E=2+127=129
那么,第一位的符号位s=0,有效数字M等于01后面再加21个0,凑满23位,指数E等于2+127=129,
即10000001。
所以,写成二进制形式,应该是s+E+M,即:
0 10000001 010 0000 0000 0000 0000 0000
这个32位的二进制数,还原成十进制,就是:1084227584
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)