C语言:深度刨析数据在内存中的存储——浮点型数据

一、浮点型数据及其取值范围

C语言:深度刨析数据在内存中的存储——浮点型数据_第1张图片

二、浮点型数据在内存中的存储

(一)小数的二进制

十进制转二进制

整数部分: 与整数原理相同,按照整数二进制转换的规则,写成对应的二进制数。
小数部分: 十进制小数转换成二进制小数采用乘2取整,顺序排列法。具体做法是:用2乘以十进制地小数,将积的整数部分取出,作为十分位,再用2乘以剩下的小数部分,再将积的整数部分取出作百分位,重复进行,直到达到要求的精度。
例如:将十进制1.8125转换成二进制
C语言:深度刨析数据在内存中的存储——浮点型数据_第2张图片
所以1.8125的二进制为1.1101。

二进制转十进制

把二进制数写成加权系数展开形式,按十进制的加法规则求和,即按权相加
例如:将二进制数1.1101转换为十进制
在这里插入图片描述

(二)科学计数法

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:

  • (-1)^S * M * 2^E
  • (-1)^S表示符号位,当s=0,V为正数;当s=1,V为负数。
  • M表示有效数字,大于等于1,小于2。
  • 2^E表示指数位。
    例如:对于上面的二进制浮点数101.1101,S为0,M为1.011101,E为6,则科学计数法表示为:(-1)^0 * 1.011101* 2^6
    C语言:深度刨析数据在内存中的存储——浮点型数据_第3张图片

(三)存储模型

单精度浮点型

IEEE 754规定: 对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
如图表示float型在内存中的存储:
C语言:深度刨析数据在内存中的存储——浮点型数据_第4张图片

符号位S

S的存储较为简单,只有1和0两种情况:

  • 当S等于1时,(-1)^S为负,表示负数;
  • 当S等于0时,(-1)^S为正,表示正数;

指数E

对于float型,E共有个比特8位,可表示范围 0~255,存入数据时,加上中间数127,这样做可以便可以表示负数,所以实际可保存数据范围为[-127 ,128]。例如:101.1101科学计数法表示为(-1)^0 * 1.011101* 2^6,E为6,内存中放6+127=133的二进制序列,取出时同理减123即可。

有效数字M

在保存M时,默认这个数的第一位是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

双精度浮点型

IEEE 754规定:对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
C语言:深度刨析数据在内存中的存储——浮点型数据_第5张图片
双精度浮点型与单精度浮点型存储原理基本类似,不再详细叙述,区别是

  • 对于double型,E共有个比特11位,可表示范围0~2047,存入数据时加上中间数1023,实际可表示数据范围[-1023,1024]。
  • M共有52个比特位,能表示位数更多的有效数字。

指数E的特殊情况

E全为0
E全为0时,浮点E的真实值为0-127(或者0-1023),表示一个接近于0的很小的浮点数,还原时有效数字M不加省略的1。
所以浮点数不能直接比较大小,要考虑进制转换时存在的误差,不能用’==’。

E全为1
表示浮点数的最大值或者最小值。

(四)练习题

#include
#include

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);

	system("pause");
	return 0;
}

C语言:深度刨析数据在内存中的存储——浮点型数据_第6张图片
整型9在内存中的存储:
在这里插入图片描述
若按float型取出打印,则解读为:
C语言:深度刨析数据在内存中的存储——浮点型数据_第7张图片
E为全0,所以printf("*pFloat的值为:%f\n", *pFloat)语句的结果为0.000000
浮点型9.0在内存中的存储:
C语言:深度刨析数据在内存中的存储——浮点型数据_第8张图片

这个二进制序列按整型打印时被解读为整型数据,将这个二进制序列直接转换为10进制即为打印结果:
C语言:深度刨析数据在内存中的存储——浮点型数据_第9张图片

你可能感兴趣的