浮点数在计算机中的存储

news2024/11/19 16:45:19

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

如果整数与浮点数的存储规则一致的话,这段代码的结果就该是:

n的值为:9

*pFloat的值为:9.000000

num的值为:9

*pFloat的值为:9.000000

然而,结果却是:

也就是说,浮点数的存储与整数的存储一定不同。

那么,浮点数到底是如何存储在计算机中的呢?


2. 浮点数的存储方式

2.1 标准规定

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

V = (-1)^{S} * M * 2^{E}

• (-1)^{S}表示符号位,当S=0时,V为正数;当S=1时,V为负数。

• M表示有效数字,M是大于等于1,小于2的。

• 2^{E}表示指数位

这其实相当于是规定了二进制下的科学计数法。

举例来说:

十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。

那么,按照上⾯V的格式,可以得出S=0,M=1.01,E=2。

十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。

那么,S=1,M=1.01,E=2。 

同时IEEE 754规定:

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

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

 图片来源于比特科技。

2.2 有效数字E

即使有了上面的规定,我们的问题依然没有得到解决,因为有效数字E依然是一个浮点数。

前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。 IEEE 754 规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后⾯的 xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。

这样一来,S,M,E都是以整数的形式存在了,我们就可以很好地将其存到计算机中。

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

2.3 指数E

2.3.1 存入E

首先,指数E的类型为无符号整形(unsigned int),这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上 ⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

这样做,其实就像是将坐标原点搬到了中间数的位置,小于中间数的就表示负数,大于中间数的就表示正数。

2.3.2 取出E

从内存中取出E还可以分为三种情况:

1. E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1。 比如:0.5 的⼆进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其 阶码为-1+127(中间值)=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位 00000000000000000000000,则其⼆进制表示形式为:

0 01111110 00000000000000000000000

2. E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,而是还原为0.xxxxxx的小数。因为无论什么数,乘上2^{-127}都会变成小到忽略不计的数,这样做是为了表示±0,以及接近于0的很小的数字。 

例如:

0 00000000 00100000000000000000000

 E全为1

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

例如:

0 11111111 00010000000000000000000


3. 对开头的代码进行解析

既然我们已经知道了浮点数在内存中的存储规则,那我们要如何解释开头那段代码的结果呢?

#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;
}

3.1 第一部分

第一步将整数9存储到int类型的n当中,那么n存储在内存中的二进制补码就是:

00000000000000000000000000001001

 将n的地址强转为float*之后赋值给pFloat,而对于pFloat,它对存储到n中的数据是这样来理解的:

0 00000000 00000000000000000001001

即S=0,E=-127, M=0.00000000000000000001001

也就是我们刚才谈到的E为全零的情况。所以,此时对于pfloat来说,n中存的是零。

3.2 第二部分

第一步将浮点数9.0存到*pFloat指向空间(n)中,按照浮点数存储的规则,我们先将9.0改写为(-1)^{0} * 1.001 * 2^{3},对应的二进制序列就是:

0 10000010 00100000000000000000000

而n本身会将这段二进制序列当作是整数

 01000001000100000000000000000000

解析出来的数据就是1091567616。


 4. 总结

浮点数的存储与整数的存储规则不同,其遵循IEEE 754的规定来存储。

值得注意的是,由于M(有效数字)的位数是有限的,所以并不是所有浮点数都能精确存储在float类型的数据之中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1540036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Node.js】npx

概述 npx 可以使用户在不安装全局包的情况下&#xff0c;运行已安装在本地项目中的包或者远程仓库中的包。 高版本npm会自带npx命令。 它可以直接运行 node_modules/.bin 下的 exe 可执行文件。而不像之前&#xff0c;我们需要在 scripts 里面配置&#xff0c;然后 npm run …

相交链表:寻找链表的公共节点

目录 一、公共节点 二、题目 三、思路 四、代码 五、代码解析 1.计算长度 2.等长处理 3.判断 六、注意点 1.leetcode的尿性 2.仔细观察样例 3.经验总结 一、公共节点 链表不会像两直线相交一样&#xff0c;相交之后再分开。 由于单链表只有一个next指针&#xff0…

MySQL 8.0-索引- 不可见索引(invisible indexes)

概述 MySQL 8.0引入了不可见索引(invisible index)&#xff0c;这个在实际工作用还是用的到的&#xff0c;我觉得可以了解下。 在介绍不可见索引之前&#xff0c;我先来看下invisible index是个什么或者定义。 我们依然使用拆开来看&#xff0c;然后再把拆出来的词放到MySQL…

Redis高级数结构HyperLogLog

HyperLogLog 概述 概述。 HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法&#xff0c;通过HyperLogLog可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是IP、Email、ID等 如果你负责开发维护一个大型的网站&#xff0c;有一天产…

使用 VMWare 安装 Android-x86 系统(小白版)

文章目录 VMWare 介绍Android 系统介绍概述最终效果前置步骤开始安装 VMWare 介绍 VMware Workstation是VMware公司开发的一款桌面虚拟化软件。它允许用户在一台物理计算机上同时运行多个操作系统&#xff0c;每个操作系统都在自己的虚拟机中运行。这使得用户可以在同一台计算…

如何使用swiprt插件

首先可以来到swiper网站看文档(中文) swiper网址地点 可以在这里面去下载swiper版本插件 需要注意的是从Swiper7开始&#xff0c;容器默认类名由’.swiper-container’变更为’.swiper’ 下载后呢 找到swiper-bundle.min.js和swiper-bundle.min.css文件 并放在你的项目中&…

Apollo配置中心

一、介绍 简要介绍 Apollo&#xff08;阿波罗&#xff09;是携程框架部门研发的分布式配置中心&#xff0c;能够集中化管理应用不同环境、不同集群的配置&#xff0c;配置修改后能够实时推送到应用端&#xff0c;并且具备规范的权限、流程治理等特性&#xff0c;适用于微服务…

在Linux中同一个tomcat出现多个进程

第一步&#xff0c;查看服务器所有的启动进程。 命令&#xff1a;top -c 第二步&#xff0c;通过点击“shiftM”&#xff0c;按照内存大小排序&#xff1b;点击“shiftP”&#xff0c;按照CPU大小排序。 在[COMMAND]列找到相同的tomcat进程&#xff0c;可以得到对应的PID。 …

【JavaEE初阶系列】——单例模式 (“饿汉模式“和“懒汉模式“以及解决线程安全问题)

目录 &#x1f6a9;单例模式 &#x1f388;饿汉模式 &#x1f388;懒汉模式 ❗线程安全问题 &#x1f4dd;加锁 &#x1f4dd;执行效率提高 &#x1f4dd;指令重排序 &#x1f36d;总结 单例模式&#xff0c;非常经典的设计模式&#xff0c;也是一个重要的学科&#x…

iStoreOS R4S软路由结合内网穿透实现公网远程本地电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

(2022级)成都工业学院软件构造实验二:面向对象软件构造

写在前面 1、基于2022级软件工程实验指导书 2、代码仅提供参考 3、如果代码不满足你的要求&#xff0c;请寻求其他的途径 运行环境 window11家庭版 IntelliJ IDEA 2023.2.2 jdk17.0.6 实验要求 任务&#xff1a;在第2章构造任务的基础上用面向对象构造技术&#xff0c…

错误centos docker版本过低导致 is not a valid repository/tag: invalid reference format

文章目录 错误centos docker版本过低导致 is not a valid repository/tag: invalid reference format1、查看免费主机刚才下载的docker版本2、卸载旧版本3、安装yum依赖包4、安装镜像信息5、安装docker CE6、查看docker版本7、再次运行就成功了&#xff01;&#xff01;&#x…

Codeforces Round 930 (Div. 2)(A,B,C,D)

比赛链接 C是个交互&#xff0c;D是个前缀和加二分。D还是很难写的。 A. Shuffle Party 题意&#xff1a; 您将得到一个数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1​,a2​,…,an​ 。最初&#xff0c;每个 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n 对应 a i i a_ii…

STM32 使用gcc编译介绍

文章目录 前言1. keil5下的默认编译工具链用的是哪个2. Arm编译工具链和GCC编译工具链有什么区别吗&#xff1f;3. Gcc交叉编译工具链的命名规范4. 怎么下载gcc-arm编译工具链参考资料 前言 我们在STM32上进行开发时&#xff0c;一般都是基于Keil5进行编译下载&#xff0c;Kei…

QT文件读写操作和内容提取

访问IO设备&#xff0c;需要先调用open()来设置正确的OpenMode(例如ReadOnly或ReadWrite) 打开设备后后&#xff0c;使用write() 或putChar() 写入数据到文件和设备&#xff0c;并通过调用read()&#xff0c;readLine() 或readAll() 进行读取&#xff1b;使用完设备后&#xf…

深度学习十大算法之长短时记忆网络(LSTM)

一、长短时记忆网络&#xff08;LSTM&#xff09;的基本概念 长短时记忆网络&#xff08;LSTM&#xff09;是一种特殊类型的循环神经网络&#xff08;RNN&#xff09;&#xff0c;主要用于处理和预测序列数据的任务。LSTM由Hochreiter和Schmidhuber于1997年提出&#xff0c;其…

腾讯云GPU云服务器_并行计算_弹性计算_AI_深度学习

腾讯云GPU服务器是提供GPU算力的弹性计算服务&#xff0c;腾讯云GPU服务器具有超强的并行计算能力&#xff0c;可用于深度学习训练、科学计算、图形图像处理、视频编解码等场景&#xff0c;腾讯云百科txybk.com整理腾讯云GPU服务器租用价格表、GPU实例优势、GPU解决方案、GPU软…

【Word自动化办公】使用python-docx对Word进行操作

目录 一、环境安装 二、文档各组成结构获取 2.1 组成结构讲解 2.2 段落run对象的切分标准 三、获取整篇文档内容 四、写入指定样式的数据 4.1 通过add_paragraph与add_run参数添加样式 4.2 单独设置文本样式 五、添加标题 六、换行符&换页符 七、添加图片数据 …

pytest之yaml格式测试用例读写封装

pytest之yaml格式测试用例读写封装 pytest之parametrize&#xff08;&#xff09;实现数据驱动YAML格式测试用例读/写/清除/封装结构类型Maps类型数组类型 pytestparametrizeyamltest_api.pyget_token.yaml pytest之parametrize&#xff08;&#xff09;实现数据驱动 pytest.ma…

文件上传二—WEB攻防-PHP应用文件上传中间件CVE解析第三方编辑器已知CMS漏洞

演示案例&#xff1a; PHP-中间件-上传相关-Apache&NginxPHP-编辑器-上传相关-第三方处理引用PHP-CMS源码-上传相关-已知识别到利用 #PHP-中间件-上传相关-Apache&Nginx 复现漏洞环境&#xff1a;vulhub &#xff08;部署搭建看打包视频&#xff09; 由于PHP搭建常用中…