【C语言系列】—深度解剖数据在内存中的存储(二)-浮点型

꧁   各位大佬们好!很荣幸能够得到您的访问,让我们一起在编程道路上任重道远!꧂

☙ 博客专栏:【C生万物】

⛅ 本篇内容简介:深度解剖浮点型数据在内存中是如何存储的!

⭐ 了解作者:励志成为一名编程大牛的学子,目前正在升大二的编程小白。

励志术语:编程道路的乏味,让我们一起学习变得有趣!

✂   正文开始


文章目录

前言

常见的浮点数

浮点数存储的例子

浮点数存储规则

IEEE 754 规定

IEEE 754对有效数字M和指数E,还要一些特别的规定

对有效数字M的规定

对指数E的规定

存储指数E时

从内存中读取出E时

解释上面为什么运行结果会是那样!


前言

在前面的深度解剖数据在内存中的存储(一)中,我们详细介绍了整形在内存中的存储以及数据是以16进制如何存储在内存中涉及的大小端问题,现在我们来详细讨论一下浮点型的数据是如何存储在内存中的。

常见的浮点数

比如:Π==3.1415926....

1E10==1.0*10^10

在之前说过整型家族,下面是浮点数家族,包括:float 、double、 long double 类型

浮点数表示的范围在 float.h文件中定义。

浮点数存储的例子

#include<stdio.h>

int main()
{
	int a = 9;
	float* p = (float*)&a;
	printf("a的值为:%d\n", a);// 以整数的形式打印a
	printf("*p的值为:%f\n", *p);//*解引用找到a,以浮点型打印出a
	*p = 9.0;//a被赋值9.0
	printf("num的值为:%d\n", a);//a以整型的形式打印
	printf("*p的值为:%f\n", *p);//以浮点型打印a的值
	return 0;
}

这打印的结果是什么呢?为什么?我们来先看结果,等会给各位讲述原因!

 是不是跟预想的不太一样,好!要弄懂为什么会出现这样的结果,我们首先就要了解一下浮点数的存储规则。

浮点数存储规则

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

· (-1)^S * M * 2^E

· (-1)^S表示符号位,当S=0,V为正数,当S=1,V为负数

·   M表示有效数字,大于等于1,小于2

·   2^E表示指数位

什么意思呢,我们来举几个例子:

比如:V=5.0f

写成二进制的形式就是 101.0,相当于1.01*2^2。

得出此时 S=0,M=1.01 ,E=2。

当 V=9.5f时,

写成二进制的形式就是 1001.1,相当于 1.0011*2^3。

为什么小数位会是 1 呢,看一张小图就了解了 ------->

 当然也有写成二进制不能精确小数点后面的数字的,比如 V=9.6f,它就永远不可能精确,永远离原来的数差一点点。

IEEE 754 规定

对于32位的浮点数,即(float类型),最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。

对于64位的浮点数,即(double类型),最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

IEEE 754对有效数字M和指数E,还要一些特别的规定

对有效数字M的规定

前面说到了,M  [1,2] ,也就是说M可以写成1.xxxxxxx的形式其中xxxxxxx表示小数部分。

在计算机内部存储M时,默认这个数的第一位总是1,因此在存储时可以被舍去,只保留后面的小数部分。

例如:存储1.01时,M中只保存01,后面不足的用0补齐,就要在拿出的时候就不会发生变化,等到读取时,再把小数点前面的1加上,这样做的目的,就是为了节省1位有效数字,使得更加精确一些,等于M中保存了24位有效数字。

对指数E的规定

存储指数E时

首先,E为一个无符号的正数(unsigned int)

就代表,如果E为8位数,取值范围为 0~255,如果为11位时取值范围为0~2047,我们知道在科学计数法中,E可以是负数的存在,所以规定存入内存时的E必须加上一个中间数,

·  8位的E:加上127

·  11位的E:加上1023

例如:在存储1.01*2^2时,此时的E为2,在存储中要加上127,即2+127=129

所以存储在E上的8个bit位为:10000001

从内存中读取出E时

可以分成三种情况:

① E不全为0或者不全为1时

规定:指数E的计算值减去127(或者减去1023),得到真实值,再将有效位M前加上第一位的1。

举个例子:

② E全为0时

这时,浮点数的指数E=1-127(或者1-1023),即为真实值,为什么呢?

想一下,当E全为0时,肯定原来的E为-127+127=0,例:1.01*2^(-127) 这样的数,大家想一下有多小,有效数字M不在加上第一位的1,而是还原为0.xxxxxxx的小数,这样做是为了表示±0,以及接近于0的很小的数字。

③E全为1时

这时,如果有效数字M全为0,表示±无穷大(正负号取决于符号位S)。

解释上面为什么运行结果会是那样!

详细解释我会放在代码中的注释中会更加的直观,以及理解:

#include<stdio.h>

int main()
{
	int a = 9;
	// 00000000 00000000 00000000 00001001   9的补码
	float* p = (float*)&a;
	// 0 00000000 00000000000000000001001
	// E全为0,是一个无限接近0的数,打印小数点后6位时,忽略后面的二进制位
	printf("a的值为:%d\n", a);// 9  以整数的形式打印
	printf("*p的值为:%f\n", *p);// 9通过%f的形式打印出来  0.000000
	// 0 00000000 00000000000000000001001  
	// S    E          M
	// E全为0,1-127=-126
	// M=0.000000000000000000000001001
	// 值为 (-1)^0 *0.0000000000000000000000001001*2^-126 无限接近与0的数
	*p = 9.0;
	// 1001.0
	// 1.0010 * 2^3
	// S=0,E=3,M=1.0010     3+127=130
	// 浮点型存入为整形  0 10000010 00100000000000000000000
	// 最高位是0 正数,直接拿出打印
	printf("num的值为:%d\n", a);// 浮点型9.0以%d的形式打印出来
	printf("*p的值为:%f\n", *p); // 9.0 (6位小数)
}

 好了,浮点型如何在内存中的存储就介绍到这里了,我们不深入去探索,只是了解一下存储的规则是怎么样的就可以了,读到这里了,给博主一个关注吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

甘宸しぐれ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值