C语言【整数与浮点数的存储区别】

news2024/12/26 20:59:25

例题引入

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

这输出的是什么呢?
在这里插入图片描述
为什么这样呢?
这就涉及到了整数与浮点数在内存中存储方式的区别了。

一.整数在内存中的存储

我们之前在操作符学过:整数的二进制表示方式有三种,即原码、反码和补码。
三种表示方式都有符号位和数值位,符号位都是用0来代表“正”,1代表代表“负”。
以整型(int)为例;整型一共有32个比特位,其中第1位代表符号位,剩下的都是数值位。
在这里插入图片描述

1.1正整数与负整数的“原反补”区别

正整数的原码、反码和补码都是相同的
负整数的三种表达方式各有不同:

原码:直接将属数值按照正负数的形式翻译成二进制
反码:不改动原码的符号位,其他位按位取反
补码:反码+1

小补充(补码转原码有两种方式):

第一种:补码-1 ——》 符号位不变,其他位按位取反
第二种:补码符号位不变,其他位按位取反 ——》再+1

在这里插入图片描述

对于整数来说:内存其实存放的整型的补码
为什么呢?
因为使用补码,可以将符号位和数值位进行统一处理
同时,加法和减法也能统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

2.浮点数在内存中的存储

在上面的代码中,num*pfloat在内存中明明是同一个数,可为什么浮点数和整数的解读结果会差别的如此之大?
想要知道原因,一定要知道浮点数在内存的表示方式

2.1国际标准IEEE(电气电子工程师协会)754

根据国际标准IEEE 754,任意一个二进制浮点数V可以表示为下面的形式:

V = ( − 1 ) S ∗ M ∗ 2 E V = (-1)^S * M * 2^E V=(1)SM2E
( − 1 ) S (-1)^S (1)S表示符号位,当S = 0时,V为正数;当S = 1时,V为负数
M表示有效数字,M是大于等于1,小于2的(因为是二进制,如果大于2就代表还可以拆解)
2 E 2^E 2E表示指数位

举例

十进制的7.0写出二进制是111.0,就相当与 1.11 ∗ 2 2 1.11*2^2 1.1122

按照上面的公式就可以知道,S = 0,M = 1.11,E = 2

-7.0的二进制为-1.11,就相当与 − 1.11 ∗ 2 2 -1.11*2^2 1.1122

S = 1, M = 1.11,E = 2

IEEE 754规定

对于32位的浮点数,最高的1位存储S(符号位),接着8位存储指数E,剩下的23位存储有效数字M。
对于64位的浮点数,最高的1位存储S(符号位),接着11位存储指数E,剩下的52位存储有效数字M。
在这里插入图片描述
在这里插入图片描述

2.2浮点数存储的过程

IEEE 745对有效数字M和E,还有一些特别规定

有效数字M

前面说过 ,1 <= M < 2,也就是说,M可以写成1.xxxxx的形式,其中xxxxx表示小数部分。
IEEE 745规定,计算机在保存M时,这第一位总是1 ,因此这个1可以被省略,只保存后面的小数部分。例如保存1.01时,只保存小数位01,等到要读取的时候,再把1加上去,这样做的目的是节省1位有效字符位,可以更精确的储存数据。

指数E的情况就有些复杂

首先,E是一个无符号整型(unsigned int);
这样就意味着,如果E是不会出现负数的情况。但是我们知道,在科学技术发中的E是可以为负数的,所以IEEE 745规定,在存储E的真实值时必须要加中间数,对于8位的E来说,这个中间数为127;对于11的E来说,这个中间数为1023。
例如:

2 11 2^{11} 211的E是11,所以保存为32位浮点数时,必须保存成11+127 = 138,即1000 1010
2 − 10 2^{-10} 210的E是-10,所以保存为32位浮点数时,必须保存为-10+127 = 117,即0111 0101

2.3浮点数读取的过程

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

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

这时,浮点数的读取就会采取以下规则,即指数E的值减去127(或1023),得到真实值,再将有效数字M的前面加上第一位的1.
例如:
0.5存放的二进制为0.1,由于规定M必须大于等于1,即将小数点往右移1一位,则为1.0*2^{-1},其E就要为-1+127 = 126,表示01111110,尾数的1.0去掉1,为0,小数部位不足23位会补0,直到补齐23位,二进制表示为:

 0 01111110 00000000000000000000000
E为全0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M也不会加上1,而是会还原成0.xxxxxxxx的小数。这样做是为了表示 ± 0 \pm0 ±0,以及接近于0的很小的数字。

0 00000000 00000000000000000001001
E为全1

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

0 11111111 00000000000000000000000

好了,关于浮点数的表示规则,就说到这里。

3.案例分析

我们回到一开始的例子;

第一段代码

	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n",n);//9
	printf("*pFloat的值为:%f\n",*pFloat);//0.000000

先看第一段,为什么9还原成浮点数,就成了0.000000?

9以整数的形式存储在内存中,得到如下二进制序列:

0000 0000 0000 0000 0000 0000 0000 1001

首先,我们将9的二进制序列按照浮点数的形式来拆解,
得到第一位符号位S = 0;
后8位的指数E = 0000 0000;
最后23位有效数字M = 000 0000 0000 0000 0000 1001

因为指数E全为0,所以符合第二种情况(E为全0),因此,浮点数就写成了:
V = ( − 1 ) 0 ∗ 0.00000000000000000001001 ∗ 2 − 126 = 1.001 ∗ 2 − 146 V = (-1)^0 * 0.000 0000 0000 0000 0000 1001*2^{-126} = 1.001*2^{-146} V=(1)00.000000000000000000010012126=1.0012146
我们可以发现V是一个很小的且接近与0的正数,所以以十进制表示就是0.000000

第二段代码

	*pFloat = 9.0;
	printf("num的值为:%d\n",n);//1091567616
	printf("*pFloat的值为:%f\n",*pFloat);//9.0

再看第二段,浮点数9.0,为什么打印为整数是1091567616
首先,浮点数9.0转化为二进制为1001.0,换成科学技术法为: 1.001 ∗ 2 3 1.001*2^3 1.00123
所以: 9.0 = ( − 1 ) 0 ∗ ( 1.001 ) ∗ 2 3 9.0 = (-1)^0 * (1.001)*2^3 9.0=(1)0(1.001)23
那么,第一位的符号位S = 0;
指数E符合第一种情况(不为全0或不为全1)
E = 3 + 127 = 130 E = 3+127 = 130 E=3+127=130二进制表示为10000010
有效数字M为001后面加20个0,补满23位。

所以写成二进制,为S+E+M,即:

0 10000010 001 0000 0000 0000 0000

这个32位的二进制数,被当做整数来解析的时候,就是整数再内存中的补码,因为符号位为0,原反补都相同,所以原码翻译就是10911567616

结语

感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!

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

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

相关文章

MySQL知识整理

MySQL知识整理 基础第一讲&#xff1a;基础架构&#xff1a;一条SQL查询语句是如何执行的&#xff1f;架构尽量减少长连接的原因和方案为什么尽量不要依赖查询缓存 索引第四讲&#xff1a;深入浅出索引&#xff08;上&#xff09;第五讲&#xff1a;深入浅出索引&#xff08;下…

4月12日重新安排行程

332.重新安排行程 332. 重新安排行程 - 力扣&#xff08;LeetCode&#xff09; 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机…

ArcGIS Desktop使用入门(三)图层右键工具——标注要素、将标注转换为注记

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…

Traefik的EntryPoints是什么?

在探索 Traefik —— 这款极受欢迎的现代反向代理和负载均衡器时&#xff0c;理解其核心组件是非常重要的。其中&#xff0c;EntryPoints 是 Traefik 中一个关键概念&#xff0c;它直接关系到如何接收和处理进入的网络流量。&#x1f511;&#x1f6a6; 1. Traefik 的 EntryPo…

Git以及Gitlab的快速使用文档

优质博文&#xff1a;IT-BLOG-CN 安装git 【1】Windows为例&#xff0c;去百度下载安装包。或者去官网下载。安装过秳返里略过&#xff0c;一直下一步即可。丌要忉记设置环境发量。 【2】打开cmd&#xff0c;输入git –version正确输出版本后则git安装成功。 配置ssh Git和s…

前端开发攻略---Vue实现防篡改水印的效果。删除元素无效!更改元素属性无效!支持图片、元素、视频等等。

1、演示 2、水印的目的 版权保护&#xff1a;水印可以在图片、文档或视频中嵌入作者、品牌或版权所有者的信息&#xff0c;以防止未经授权的复制、传播或使用。当其他人使用带有水印的内容时&#xff0c;可以追溯到原始作者或版权所有者&#xff0c;从而加强版权保护。 身份识…

windows 更新显卡

下载网址&#xff1a;NVIDIA GeForce 驱动程序 - N 卡驱动 | NVIDIA 选择本地显卡的型号

spring高级篇(一)

1、ApplicationContext与BeanFactory BeanFactory是ApplicationContext的父级接口&#xff1a;&#xff08;citlaltu查看类关系图&#xff09; 在springboot的启动类中&#xff0c;我们通过SpringApplication.run方法拿到的是继承了ApplicationContext的ConfigurableApplicatio…

【前缀合】Leetcode 连续数组

题目解析 525. 连续数组 寻找一个子数组&#xff0c;这个子数组中包含相同数目的0和1&#xff0c;但是这个子数组需要最长的 算法讲解 只需在[0,i]寻找一段区间使得这一段区间的和也等于sum即可 细节问题&#xff1a;1. 这里的哈希表的value存的是下标&#xff0c;因为需要找…

ccframe系统的链路追踪,用户ID追踪的实现

需求 之前ccframe cloud V1用的是springcloud微服务&#xff0c;只需要在header将jwttoken一直传下去就没事&#xff0c;最近弄V2转dubbo发现用户id没有自动保存进数据库表。于是开始研究dubbo如何追踪&#xff0c;顺便把链路追踪ID的问题给一并解决掉。 理论 MDC MDC&…

TSINGSEE青犀AI智能分析网关V4吸烟/抽烟检测算法介绍及应用

抽烟检测AI算法是一种基于计算机视觉和深度学习技术的先进工具&#xff0c;旨在准确识别并监测个体是否抽烟。该算法通过训练大量图像数据&#xff0c;使模型能够识别出抽烟行为的关键特征&#xff0c;如烟雾、手部动作和口部形态等。 在原理上&#xff0c;抽烟检测AI算法主要…

跟TED演讲学英文:The dark side of competition in AI by Liv Boeree

The dark side of competition in AI Link: https://www.ted.com/talks/liv_boeree_the_dark_side_of_competition_in_ai Speaker:Liv Boeree Date: October 2023 文章目录 The dark side of competition in AIIntroductionVocabularyTranscriptSummary后记 Introduction Co…

微服务项目——谷粒商城

文章目录 一、项目简介&#xff08;一&#xff09;完整的微服务架构微服务划分图&#xff08;二&#xff09;电商模式1.B2B 模式2.B2C 模式3.C2B 模式4.C2C 模式5.o2o 模式2.谷粒商城 &#xff08;三&#xff09;项目技术&特色&#xff08;四&#xff09;项目前置要求 二、…

Vue3(二):报错调试,vue3响应式原理、computed和watch,ref,props,接口

一、准备工作调试 跟着张天禹老师看前几集的时候可能会遇到如下问题&#xff1a; 1.下载插件&#xff1a;Vue Language Features (Volar)或者直接下载vue-offical 2.npm run serve时运行时出现错误&#xff1a;Error: vitejs/plugin-vue requires vue (&#xff1e;3.2.13) …

基于java+springboot+vue实现的居家养老健康管理系统(文末源码+Lw)23-313

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装智慧社区居家养老健康管理系统软件来发挥其高效地信息处理…

Filebeat+Kafka+ELK 的服务部署

一. kafka 架构深入 1.1 Kafka 工作流程及文件存储机制 Kafka 中消息是以 topic 进行分类的&#xff0c;生产者生产消息&#xff0c;消费者消费消息&#xff0c;都是面向 topic 的。 topic 是逻辑上的概念&#xff0c;而 partition 是物理上的概念&#xff0c;每个 partit…

B004-表达式 类型转换 运算符

目录 表达式数据类型转换自动转换强制转换 运算符数学运算符自增自减运算符i与 i的区别 赋值运算符比较运算符位运算符(了解)逻辑运算符三目运算符 表达式 /*** 表达式定义&#xff1a;由常量 变量 运算符 括号组成的算式&#xff0c;为了按照一定的运算规则计算出结果值* 括…

二叉搜索树--搜索二维矩阵 II

题目描述 编写一个高效的算法来搜索 m * n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,…

基于springboot实现桂林旅游景点导游平台管理系统【项目源码+论文说明】计算机毕业设计

基于springboot实现桂林旅游景点导游平台管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了桂林旅游景点导游平台的开发全过程。通过分析桂林旅游景点导游平台管理的不足&#xff0c;创建了一个计算…

洛谷P1109 学生分组

#先看题目 题目描述 有 n 组学生&#xff0c;给出初始时每组中的学生个数&#xff0c;再给出每组学生人数的上界 R 和下界 L (L≤R)&#xff0c;每次你可以在某组中选出一个学生把他安排到另外一组中&#xff0c;问最少要多少次才可以使 N 组学生的人数都在 [L,R] 中。 输入…