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

✨✨欢迎大家来到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
// 符号   指数          有效数字

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

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

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

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

相关文章

Linux 时间系统调用

UNIX及LinuxQ的时间系统是由「新纪元时间」Epoch开始计算起。Epoch是指定为1970年1月1日凌晨零点零分零秒&#xff0c;格林威治时间。目前大部份的UNX系统都是用32位来记录时间&#xff0c;正值表示为1970以后&#xff0c;负值则表示1970年以前。 对于当前时间到Epoch 我们用两…

2024蓝桥杯每日一题(DFS)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;奶牛选美 试题二&#xff1a;树的重心 试题三&#xff1a;大臣的差旅费 试题四&#xff1a;扫雷 试题一&#xff1a;奶牛选美 【题目描述】 听说最近两斑点的奶牛最受欢迎&#xff0c;…

后端系统开发之——创建SpringBoot工程

原文地址&#xff1a;后端框架系统开发之——创建SpringBoot工程 - Pleasure的博客 下面是正文内容&#xff1a; 前言 现在的市场环境&#xff0c;如果你单单只是作为前端工程师或者是后端工程师&#xff0c;在开发Web应用的时候都需要去读取企业提供的接口文档。而当你前后端…

没想到打脸这么快,AI程序员已经出发了!

大家好啊&#xff0c;我是豆小匠。 先介绍一下本期的主角&#xff1a;Devin&#xff0c;世界上第一位AI程序员&#xff0c;由2023年11月成立的10人初创公司Cognition AI开发。 1. AI程序员已经能做到什么程度 3月13日&#xff0c;Cognition AI公司在X平台&#xff08;原推特&…

关于volatile与指令重排序的探讨

写在开头 在之前的学习我们了解到&#xff0c;为了充分利用缓存&#xff0c;提高程序的执行速度&#xff0c;编译器在底层执行的时候&#xff0c;会进行指令重排序的优化操作&#xff0c;但这种优化&#xff0c;在有些时候会带来 有序性 的问题。 那何为有序性呢&#xff1f;…

LeetCode Python - 57. 插入区间

目录 题目描述解法方法一&#xff1a;排序 区间合并方法二&#xff1a;一次遍历 运行结果方法一&#xff1a;排序 区间合并方法二&#xff1a;一次遍历 题目描述 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表。 在列表中插入一个新的区间&#xff0c;你需…

MySQL语法分类 DQL(1)基础查询

//语法 select 字段列表 from 表名列表 where条件列表 group by分组字段 having 分组后的条件 order by排序 limit 分页限定为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),ma…

数据的响应式:实现动态数据驱动的技巧

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

rt-thread之通讯协议modbus软件包的使用记录(lwip+modbus组合)

前言 使用freemodbus软件包使用网口通讯(sallwip)ip地址使用dhcp动态获取 软件包 相关宏定义 /*-----------------------------------------NET 宏定义-------------------------------------------*/#define RT_USING_SAL #define SAL_INTERNET_CHECK /* Docking with prot…

App拉新必备!Xinstall渠道追踪,让每一分钱都花在刀刃上

在移动互联网时代&#xff0c;App已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;对于App开发者来说&#xff0c;如何有效地进行拉新&#xff0c;提高用户留存率&#xff0c;一直是一个难题。而渠道追踪&#xff0c;作为App推广过程中的重要环节&#xff0c;往往被忽…

Prometheus + Grafana 监控解决方案介绍及部署

Prometheus Grafana 监控解决方案介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一套开源的 监控&报警&时间序列 数据库 的组合&#xff0c;起始是由SoundCloud公司开发。 随着发展&#xff0c;越来越多公司和组织接受采用Prometheus&#xff0c;社区也十分活…

【Spark编程基础】RDD 编程初级实践(附源代码)

目录 一、实验目的二、实验平台三、实验内容1.spark-shell 交互式编程2.编写独立应用程序实现数据去重3.编写独立应用程序实现求平均值问题 一、实验目的 1、熟悉 Spark 的 RDD 基本操作及键值对操作&#xff1b; 2、熟悉使用 RDD 编程解决实际具体问题的方法 二、实验平台 …

【LabVIEW FPGA入门】浮点数类型支持

如今&#xff0c;使用浮点运算来设计嵌入式系统的需求变得越来越普遍。随着 FPGA 因其固有的大规模并行性而在浮点性能方面继续超越微处理器&#xff0c;这种情况正在加剧。线性代数和数字信号处理 (DSP) 等高级算法可以受益于浮点数据类型的高动态范围精度。LabVIEW FPGA 通过…

【Godot4自学手册】第二十五利用PointLight2D节点点缀夜晚灯光

夜晚来临了&#xff0c;少不了灯光的出现&#xff0c;今天就用PointLight2D节点来实现夜晚的忽闪忽闪灯光效果。 一、添加场景 1、添加PointLight2D场景 单击添加新节点按钮&#xff0c;在场景面板中选择其他节点&#xff0c;在弹出创建Node对话框中选择 PointLight2D&#…

Vue中使用Lodash

Vue中使用Lodash 前言安装Lodash引用方法vue中使用1、cloneDeep 深拷贝2、uniq 数组去重3、uniqWith 数组对象去重 isEqual 深度比对4、intersection 提取数组相同元素5、chunk 数组切分6、compact去除假值7、reject:根据条件删除指定的值8、find:查找结果的第一个值9、filter:…

基于sortablejs实现拖拽element-ui el-table表格行进行排序

可以用原生的dragstart、drag、dragend、dragover、drop、dragleave实现这个效果&#xff0c;但是有现成的轮子就不要重复造了&#xff0c;看效果&#xff1a; <template><el-table :class"$options.name" :data"tableData" ref"table"…

Android Kotlin知识汇总(一)编程语言

在 2019 年 Google I/O 大会上宣布今后将优先采用 Kotlin 进行 Android 开发。Kotlin 是一种富有表现力且简洁的编程语言&#xff0c;不仅可以减少常见代码错误&#xff0c;还可以轻松集成到现有应用中。如果您想构建 Android 应用&#xff0c;建议您从 Kotlin 开始着手&#x…

java.lang.NoSuchMethodException异常解决

标题 java.lang.NoSuchMethodException异常的正确解决方法摘要&#x1f680; 异常介绍&#x1f9d0; 异常原因分析&#x1f6e0; 解决方法核对方法名称和参数使用正确的方法签名调整方法访问权限 &#x1f4dd; 解决步骤详解&#x1f5a5; 代码案例演示❓ QA部分Q: 如何区分jav…

使用canvas实现图纸标记及回显

图纸 图纸标记后的效果图 最近做的一个qms项目里面&#xff0c;需要前端在图纸上实现标记及标记后的内容还要能够回显&#xff0c;然后后端通过标记的点&#xff0c;去读取标记图纸的内容&#xff0c;如一些公式、数据之类的&#xff0c;目前实现的功能有 在图纸上面进行矩形…

【论文阅读】DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer

DiffSpeaker: 使用扩散Transformer进行语音驱动的3D面部动画 code&#xff1a;GitHub - theEricMa/DiffSpeaker: This is the official repository for DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer paper&#xff1a;https://arxiv.org/pdf/…