【C语言入门】浮点型数据在内存中的存储

本文详细介绍了C语言中浮点型数据在内存中的存储过程,遵循IEEE754标准,包括单精度和双精度的存储模型,以及有效数字M和指数E的处理方法。通过实例解析浮点数在内存中取值规则,如E全为0、全为1的情况。
摘要由CSDN通过智能技术生成

✨✨欢迎大家来到Celia的博客✨✨

🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉

所属专栏:C语言

个人主页Celia's blog~

目录

​编辑

引言

引例

一、浮点型在内存中的存储方式

1.1 国际标准IEEE754

1.2 浮点型在内存中的存储过程

1.2.1 单精度与双精度的存储模型

 1.2.2 有效数字 M 和指数 E 的特殊规定

(1)有效数字M

(2)指数E

二、浮点数在内存中取的过程

2.1 E不全为0也不全为1

2.2 E全为0

2.3 E全为1

三、引例解析


 

引言

  我们知道,整型数据在内存中以补码的形式存储,字符型数据在内存中以ASCII码的形式存储,其本质都是一个二进制序列,但在C语言中,浮点型的存储方式与其他数据类型大不相同,本篇文章将会简单介绍浮点型数据在内存中的存储方式。

引例

  我们先来看接下来的代码,它的输出结果是什么?

#include<stdio.h>
int main()
{
	int a = 5;

	float* p = (float*)&a;
	printf("%f\n", *p);//打印指针p所指向的数据
	*p = 6.0;
	printf("%d\n", a);//以整型形式打印a变量
	return 0;
}

 运行结果:

是不是和预想的不同?这个例子能有效地证明浮点型数据在内存中有着独特的存储方式。

一、浮点型在内存中的存储方式

1.1 国际标准IEEE754

“IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用,IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。”

  国际标准IEEE(电气和电子工程协会)754规定了任意一个浮点数都可以表示成以下的形式:

  • V = (-1)^S  *  M  *  2^E
  • (-1)^S表示符号位,用于表示正负
  • M为有效数字(1<M<2)
  • 2^E表示指数位

比如:

  • 十进制的5.0可以表示成二进制为:101.0,相当于(-1)^0 * 1.01 * 2^2
  • 按照以上形式:S=0,M=1.01,E=2
  • 所以浮点型的存储可以理解为是对S,M,E的存储

1.2 浮点型在内存中的存储过程

1.2.1 单精度与双精度的存储模型

 1.2.2 有效数字 M 和指数 E 的特殊规定

(1)有效数字M

  有效数字M的范围始终是1<M<2,相当于1.xxxxxxx,其中,xxxxxx表示小数部分,在实际存储过程中,往往会省略有效数字最前面的 1 ,只保存小数部分,等到需要取出浮点型数据的时候,再把1加到最前面,这样做可以实现多存一位小数位,实现更高的精度。

(2)指数E

  在国际标准IEEE754中规定了E是一个无符号的整数(unsigned int)。

这就说明,如果E是8位,它能表示的数据范围为0~255,如果E为11位,它能表示的数据范围为0~2047。但是在实际的科学计数法中,指数是可能出现负数的,(比如0.5可以表示为(-1)^0 * 1.0 * 2^(-1))但是E为无符号整型,这就使得它无法储存负数。为了解决这一问题,IEEE754规定,设置一个中间量,存入内存时E的真实值必须加上这个中间量,保证存入E的值为正数,在取出E时再减去中间量,这样一来,指数为负数时的存储问题就得到了解决。

单精度中间量(8位):127

双精度中间量(11位):1023

二、浮点数在内存中取的过程

2.1 E不全为0也不全为1

  在这种情况下,浮点数会采用以下规则取出并进行相应的转换:

  1. 将指数的值减去中间量,得到真实值
  2. 将有效数字M加上最前面的1

比如 :0.5 的二进制表示为0.1,按照国际标准IEEE754可以表示为 (-1)^0 * 1.0 * 2^(-1)

存储时的S为0,M为0(去掉了最前面的1并且向后补齐0),E为-1+127 = 126,以下是二进制的存储方式(单精度):

    0   01111110   00000000000000000000000
// 符号S    指数E          有效数字M

2.2 E全为0

  这种情况下,浮点数的指数E转换后的真实值为-127或-1023,说明这个数是一个很小的数,这时有效数字不再加上最前面的1,而是表示为0.xxxxxx的小数,用来近似±0的小数。

2.3 E全为1

  这种情况下,浮点数的指数E转换后的真实值为128或1024,说明这是一个很大的数,表示±无穷大。

三、引例解析

  了解了这些规则后,我们再回过头来看引例中的代码

#include<stdio.h>
int main()
{
	int a = 5;

	float* p = (float*)&a;
	printf("%f\n", *p);//打印指针p所指向的数据
	*p = 6.0;
	printf("%d\n", a);//以整型形式打印a变量
	return 0;
}

 我们先来看a变量,5的二进制表示为:

00000000000000000000000000000101

 但是在打印指针p所指向的数据a的时候是按浮点型打印,编译器会按照取浮点型的方式去理解这个二进制序列:

    0    00000000    00000000000000000000101
// 符号    指数              有效数字

显而易见,指数部分全为0,编译器会认为这是一个很小的数,打印结果为0.000000

当我们把6.0这个浮点型数据通过指针p赋值给a的内存时,会按存储浮点型数据的方式进行存储,二进制序列如下:

    0  10000001 10000000000000000000000
// 符号   指数          有效数字

按照这种方式存储之后,如果按整形数据进行打印的话,编译器在取出这个二进制序列时,并不会按照浮点型的方式取出,而是把它当作一串补码取出,打印出来自然就是很大的数了。

以上就是关于浮点型数据在内存中存储的全部内容啦~

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Celia~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值