前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浮点数在内存中的存储

浮点数在内存中的存储

作者头像
ahao
发布2024-03-19 18:46:38
550
发布2024-03-19 18:46:38
举报
文章被收录于专栏:学习学习

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

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

首先,先来说一下浮点型数字的二进制怎么表示: 例如,5.5 前面的5为整数,表示为0101 后面的0.5等于2^(-1),二进制位0.1 故5.5的二进制为0101.1

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

代码语言:javascript
复制
#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,他的二进制为

代码语言:javascript
复制
0000 0000 0000 0000 0000 0000 0000 1001

因为9是正数,所以源码等于反码等于补码,故存储在内存中就是上述二进制序列 当9被以浮点型数字拆分,就为以下序列:

代码语言:javascript
复制
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的二进制为

代码语言:javascript
复制
1000 0010

M的二进制位

代码语言:javascript
复制
001 0000 0000 0000 0000 0000 0000 

二进制序列位S+E+M 将浮点型数字9.0以存入内存,序列为

代码语言:javascript
复制
0 10000010 001 0000 0000 0000 0000 0000

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

大家有空的话可以自己尝试着联系一下。 好了,阿豪今天的分享就到这了,点个关注不迷路哦!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 浮点数在内存中的存储详解
    • IEEE 754规定:
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档