【C语言】深层理解,浮点型数据在内存中的储存

大家好呀!👋这个是付青云同学的博客,是一名大一在校生哦!😁😁
目前一直在学习C语言。🐸
写博客是为了来记录我的学习过程,同时也希望通过博客能够帮助到需要帮助的人。
如果我的博客可以帮助到你,不妨给我一个关注哦😁

前言

最近发现一个这样的代码:

int main()
{
	int i = 5;
	float* pi = (float*)&i;
	printf("i=%dn", i);
	printf("pi=%fn", *pi);
	*pi = 5.0;
	printf("i=%dn", i);
	printf("pi=%fn", *pi);
	return;
}

它运行之后的结果是这样的?
请添加图片描述

就感觉挺有意思的,但为什么会这样却并不清楚,于是查了一些资料,发现关于浮点型类型的数据在内存中的储存大有文章,因此写下了这个博客。


本人是C语言的初学者,文章若有纰漏或错误部分,还敬请指出,不胜感谢!

浮点型类型的数据在内存中的储存

关于浮点型数据

常见的浮点数:

3.14159
1E10
浮点数包括float、double、long double类型等

浮点型类型的数据在内存中的储存规则

回到前言中那个题目

int main()
{
	int i = 5;
	float* pi = (float*)&i;
	printf("i=%dn", i);
	printf("pi=%fn", *pi);
	*pi = 5.0;
	printf("i=%dn", i);
	printf("pi=%fn", *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

关于IEEE 754规定:

对于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

解题

知道了这些知识之后,我们就可以解上面的那道题了

  1. 为什么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

  1. 浮点数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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>