浮点数在内存中的存储

简介: 浮点数在内存中的存储

浮点数在内存中的存储详解

我们知道, 计算机内部实际上只能存储或识别二进制。

在计算机中, 我们日常所使用的文档, 图片, 数字等, 在储存时, 实际上都要以二进制的形式存放在内存或硬盘中, 内存或硬盘就好像是一个被划分为许多小格子的容器, 其中每个小格子都只能盛放0或1。我们日常使用的 浮点数 也不例外, 最终也要被存储到这样的二进制小格子中。(来源于知乎)

对于整形来说:数据存放内存中其实存放的是补码。

那么,对于浮点数来说,在内存中是如何存储的呢?

首先,先来说一下浮点型数字的二进制怎么表示:

例如,5.5

前面的5为整数,表示为0101

后面的0.5等于2^(-1),二进制位0.1

故5.5的二进制为0101.1

下面,我给出一段代码,大家可以先自己思考以下输出的结果

#include <stdio.h>
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);
 return 0;
 }

思考完了吧!

下面请看结果:

相信大家可能都会对这个结果产生疑问,咋就是和我想得不一样呢?(本人真爱粉,不要黑我了啊哈哈哈哈)

各位莫急,听我说!

上⾯的代码中, num 和 *pFloat 在内存中明明是同⼀个数,为什么浮点数和整数的解读结果会差别这么⼤?要理解这个结果,⼀定要搞懂浮点数在计算机内部的表⽰⽅法。

*根据国际标准IEEE(电⽓和电⼦⼯程协会) 754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
V = (−1)^S M ∗ 2^E
• (−1)^S 表⽰符号位,当S=0,V为正数;当S=1,V为负数
• M 表⽰有效数字,M是⼤于等于1,⼩于2的
• 2^E 表⽰指数位

例如:一个十进制数字5

二进制为 101.0 ,可以表示为 1.01×2^2

S=0 M=1.01 E=2

IEEE 754规定:

对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M
对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

下面用图来理解以下上述的IEEE 754规定

(图为32位)

(图为64位)

上面的IEEE 754 规定中我们提到,M的值是属于[1,2)(1到2的左闭右开区间),所以,M的值的小数点前的数只有可能是1,所以在存储的时候,M的表现形式就是" 1.XXXXXXX "默认就把1给省略了。

例如:保存1.01,保存的就只有01,小数点前的1就会省略,读取时把1加上去就可以了

这样就会节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。

接下来就到了指数E的讲解了,这个点比较重要,同时也比较复杂。

⾸先,E为⼀个⽆符号整数(unsigned int)

这意味着,如果E为8位,它的取值范围为0~ 255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的

例如:数字0.5,二进制为0.1,存储为浮点型,但是规定了M大于等于1,所以将小数点右移一位,他的存储形式就是(-1)^ 0 * 1.0*2^(-1),M中的1可以省略,故存为0,转换为23个0,E的值为-1,加上中间值127等于126,存为 01111 1110,存储如下图

所以IEEE 754规定,存⼊内存时E的真实值必须再加上这个指定的中间数,32位的条件下这个中间数就取为127;64位的条件下,这个中间数就取为1023。

例如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001

保存如下

此外,指数E还有一个重点,不能存储为全0或者全1!

废话不多说,以32位举例说明吧

例如,如果E存储为全0的话,就是说E加上中间数127后的二进制为0000 0000,大家可以想到指数E是-127,几乎趋近于0。

而存储全为1的话,就是指数E就是128,就会趋近于无穷大了

下面,我们带着知识点回到开头的练习,对其进行解析

首先,n为9,他的二进制为

0000 0000 0000 0000 0000 0000 0000 1001

因为9是正数,所以源码等于反码等于补码,故存储在内存中就是上述二进制序列

当9被以浮点型数字拆分,就为以下序列:

0 0000 0000 000 0000 0000 0000 0000 1001
//浮点数V=(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146)

这个数趋近于零,故打印浮点型为0.000000

下面看第二部分,9的二进制为1001,v=(-1)^ 0*1.001 *2^3

E=3,E+127=130,M为1.001,省略小数点前的1,将001存入内存,后面补二十个零

E的二进制为

1000 0010

M的二进制位

001 0000 0000 0000 0000 0000 0000

二进制序列位S+E+M

将浮点型数字9.0以存入内存,序列为

0 10000010 001 0000 0000 0000 0000 0000

当9以整形输出,因为为正数,所以直接将此二进制序列看作源码,用windows计算机算出十进制数值为1091567616

大家有空的话可以自己尝试着联系一下。

好了,阿豪今天的分享就到这了,点个关注不迷路哦!

相关文章
|
1月前
|
存储 JSON 监控
Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
【2月更文挑战第30天】Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
14 1
|
2天前
|
存储 算法
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
7 0
|
2天前
|
存储
数据在内存中的存储之整数存储
数据在内存中的存储之整数存储
8 0
|
9天前
|
存储 NoSQL Oracle
Oracle 12c的内存列存储:数据的“闪电侠”
【4月更文挑战第19天】Oracle 12c的内存列存储以超高速度革新数据处理,结合列存储与内存技术,实现快速查询与压缩。它支持向量化查询和并行处理,提升效率,但需合理配置以平衡系统资源。作为数据管理员,应善用此功能,适应业务需求和技术发展。
|
19天前
|
存储 C语言
数据在内存中的存储2
数据在内存中的存储2
|
19天前
|
存储 编译器
数据在内存中的存储1
数据在内存中的存储
|
30天前
|
存储 编译器 程序员
【C语言】整形数据和浮点型数据在内存中的存储
【C语言】整形数据和浮点型数据在内存中的存储
16 0
|
1月前
|
存储 小程序 C语言
【深度剖析数据在内存中的存储】C语言
【深度剖析数据在内存中的存储】C语言
|
1月前
|
存储 小程序 C语言
【C语言进阶】深度剖析数据在内存中的存储
【C语言进阶】深度剖析数据在内存中的存储
|
2月前
|
存储 编译器 C语言
C语言:数据在内存中的存储形式
C语言:数据在内存中的存储形式