浮点型在内存中的存储,与整型存储方式竟然不同

news2025/1/3 1:40:30

对于整形的存储方式,大家可以看我的上一篇文章,这篇文章来介绍浮点型在内存中存储方式。

目录

1. 问题

2. 浮点型家族:

3. 存储方式:

4. 读取方式:

5. 解题

1. 问题

我们先来看一段代码:

#include <stdio.h>
int main()
{
	int n = 9;
	float* pfloat = (float*)&n;//将int*类型的指针强制类型转换为float*
	printf("n的值为:%d\n", n);
	printf("*pfloat的值为:%f\n", *pfloat);//以%f的形式输出,要以解引用float*的方式读取

	*pfloat = 9.0;
	printf("n的值为:%d\n", n);
	printf("*pfloat的值为:%f\n", *pfloat);
	return 0;
}

 操作的都是同一块空间,但为什么读出的数据不同呢,这个可以说明整形和浮点型的数据在内存中的存储方式是不同的,至于浮点型数据怎样存储,让我们先来学习一下浮点型数据在内存中的存储,再来看一下这段代码。

首先每个数据类型都有自己的取值范围,整形家族类型的取值范围在 limit.h 文件中定义,浮点型家族类型的取值范围在 float.h 中定义 。这两个文件可以先包含,然后选中右键转到文档,也可以直接在安装目录下寻找。

2. 浮点型家族:

float    4个字节

double 8个字节

long double  16个字节

常见的浮点数:

3.14159  字面常量值

1E10      科学计数法   就是1.0*10^10

3. 存储方式:

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

(-1)^S * M * 2^E
 (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。

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

 2^E 表示指数位。

什么意思呢,举例来说∶十进制的5.0,写成二进制是101.0,相当于1.01x2^2 。那么,按照上面V的格式,可以得出S=0,M=1.01 ,E=2。
十进制的 -5.0,写成二进制是 -101.0,相当于-1.01x2^2。那么,S=1,M=1.01,E=2。
 

所以:有些浮点数在内存中是无法精确保存的,比如0.3,小数点1位是0.5,2位0.25,3位0.125,4位是0.0625,...,0.3需要0.25+....,如果一直相加的如果得不到想要的数字,那它就无法精确保存。

 IEEE 754规定:对于32位浮点数,最高的1位是符号位S,接着的是8位指数位E,剩下的23位为有效数字M。

单精度浮点型存储模型:

 对于64位浮点数,最高的1位是符号位S,接着的是11位指数位E,剩下的52位为有效数字M。

 双精度浮点数的存储模型:

 IEEE 754对有效数字M和指数E,还有一些特别规定。前面说过,M>=1&&M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。

IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

至于指数E,情况就比较复杂。

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

存储5.5 

#include<stdio.h>

int main()
{
	float f = 5.5f;
	//101.1
	//(-1)^0 * 1.011 * 2^2
	//E = 127+2 = 129  10000001
	//0 10000001 01100000000000000000000  二进制
	//S    E        M
	//40 b0 00 00 16进制  内存中就是这个
	return 0;
}

我们可以通过调试查看内存

 不懂小端存储的也可以去看我的上一篇文章。

4. 读取方式:

然后,指数E从内存中取出还可以再分成三种情况︰

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

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

2.E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示正负0,以及接近于0的很小的数字。

E全为0,说明之前在存储时E是-127,double为-1023,是一个正负无穷接近0的数。

3.E全为1

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

 当E全为1时,是255,真实值是255-127 是128,2的128的次方是很大的数字,如果是无穷大,M就会全为0,不深入研究,没有意义。

5. 解题

这时我们再看最开始的代码

#include<stdio.h>
int main()
{
	int n = 9;
	//00000000000000000000000000001001  9的补码

	float* pFloat = (float*)&n;//指针类型的意义就是为了以不同视角,权限去解引用

	printf("n的值为:%d\n", n);//9
	//0 00000000 00000000000000000001001  9的补码
	//S==0; E全为0   M==00000000000000000001001
	//E=1-127=-126  M==0.00000000000000000001001
	//(-1)^0 * 0.00000000000000000001001 *  2^-126   %f打印6位
	printf("*pFloat的值为:%f\n", *pFloat);//0.000000

	*pFloat = 9.0;//以浮点型的视角,存放浮点型的数字
	//1001.0
	//(-1)^0 * 1.001 * 2^3
	// S=0  M=1.001  E=3
	// 3+127=130
	//0 10000010 00100000000000000000000   
	//%d 打印 0是正数,不用翻译原码
	printf("n的值为:%d\n", n); //1091567616
	//0 10000010 00100000000000000000000
	//还原
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

本篇结束

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

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

相关文章

人体姿态估计

预测人体关键点有什么作用&#xff1f; 还原人体姿态&#xff0c;输出脸部、手部的关键点坐标3D空间内&#xff0c;关键点变为3维坐标&#xff0c;可以在三维空间中还原人体姿态&#xff0c;可以实现一键换装恢复3D的人体模型实现下游任务–行为理解&#xff0c;根据姿态判断人…

rocketmq-client-go注册消费者组的问题

一、前言 test环境服务启动&#xff0c;通过代码新注册一个customer group进行消费&#xff0c;服务一直报错如下&#xff1a; levelerror msg"fetch offset of mq from broker error" MessageQueue"MessageQueue [topicxxx, brokerNamebroker-a, queueId1]&q…

字节跳动面试挂在2面,复盘后,决定二战.....

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;字节的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

人体关键点检测

title: 人体关键点检测 date: 2023-06-02 21:28:46 tags: [MMPose,cv] 人体关键点检测 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9x4nhwLf-1685714024668)(https://fastly.jsdelivr.net/gh/weijia99/blog_imagemain/1685712470039%E4%BA%BA%E4…

【stm32开发】stm32+oled最小系统板资料(原理图、PCB、示例代码)【六一】

&#x1f389;欢迎来到stm32专栏~stm32oled最小系统板 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;stm32专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家能…

深度学习训练营之J5周DenseNet+SE-Net实战

深度学习训练营之J5周DenseNetSE-Net实战 原文链接方法介绍SE模块应用分析SE模块的效果对比SE模块代码实现SE模块在DenseNet当中的应用参考内容 原文链接 &#x1f4cc;第J5周&#xff1a;DenseNetSE-Net实战&#x1f4cc; &#x1f368; 本文为&#x1f517;365天深度学习训练…

UART帧格式介绍

UART及通信方式简介 UART Universal Asynchronous Receiver Transmitter 即通用异步收发器&#xff0c;是一种通用的串行、异步通信总线 &#xff0c;该总线有两条数据线&#xff0c;可以实现全双工的发送和接收&#xff0c;在嵌入式系统中常用于主机与辅助设备之间的通信…

Web3 游戏团队如何在项目发布前奠定成功基础——以真实用户支持为核心的运营策略

作者&#xff1a;lesleyfootprint.network 运营 Web3 游戏项目是一项令人兴奋且具有挑战性的任务。无论是对于 NFT 游戏还是链上多人游戏&#xff0c;建立强大且高度参与的用户群体都是游戏成功的关键因素之一。 在本文中&#xff0c;我们将探讨游戏中真实参与和机器人刷量之…

class文件中,常量池之后的相关数据解析!【class二进制文件分析】

前言&#xff1a;前段时间读《深入java虚拟机》介绍到class文件的时候&#xff0c;由于理论知识较多&#xff0c;人总感觉疲惫不堪&#xff0c;就泛泛阅读了一下。在工作中使用起来知识点知道&#xff0c;但是总是需要查阅各种资料。今天有时间&#xff0c;继续整理常量池后面的…

msvcp140.dll丢失的4个解决方法,msvcp140.dll丢失的常见原因

msvcp140.dll是Windows操作系统中的一个动态链接库文件&#xff0c;由Microsoft Visual C程序库所提供。它包含了许多C函数和类的定义&#xff0c;可以为应用程序提供一些基本服务&#xff0c;比如内存管理、文件输入/输出和网络连接等功能。我们在打开游戏或者软件的时候&…

Goby 漏洞更新 |海康威视部分iVMS系统存在文件上传漏洞

漏洞名称&#xff1a;海康威视部分iVMS系统存在文件上传漏洞 English Name&#xff1a;Some Hikvision iVMS file upload vulnerabilitie CVSS core: 9.8 影响资产数&#xff1a;15294 漏洞描述&#xff1a; 海康威视-iVMS综合安防管理平台是一套“集成化”、“数字化”、…

Redis系列----redis网络模型2

一、redis单双线程判断 一、redis单线程定义 主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理&#xff0c;这就是所谓的“单线程”。这…

VH6501干扰仪的使用

目录 1.VH6501接口介绍 2.使用场景 2.1当VH6501作为硬件接口卡作通信/监测使用时&#xff0c;使用CH1的任意接口与总线连接即可 2.2若将 VH6501 用于干扰总线&#xff0c;针对单节点干扰时则通常情况下接任意一个接口即可 2.3针对多节点干扰时&#xff0c;需要通过CH1的两个…

YCbcr to rgb 笔记

YCbCr 色彩空间的一种 YCbCr或Y’CbCr有的时候会被写作&#xff1a;YCBCR或是Y’CBCR&#xff0c;是色彩空间的一种&#xff0c;通常会用于影片中的影像连续处理&#xff0c;或是数字摄影系统中。Y’为颜色的亮度(luma)成分、而CB和CR则为蓝色和红色的浓度偏移量成份。Y’和Y…

3.4 最大字段和

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是最大子段和? 我的理解&#xff1a; 最大子段和是一个经典的问题&#xff0c;也称为最大子数组和问题。给定一个整数数组&#xff0c;要求找到…

口撕raft面试100问

1&#xff0c;Raft 协议什么作用 2&#xff0c;详细介绍 Raft 流程 我觉得以下这个流程是比较详细的了&#xff0c; 以下是带上了持久化和日志压缩的细节&#xff1a; 持久化&#xff1a;节点会定期将自己的信息&#xff0c;比如当前任期号、投票信息、日志条目和快照&#…

项目改造操作(图书管理系统为例)

目录 后端 概述 获取所有的读者的借阅卡号 获取所有的未被借阅的图书编号 进行借阅 前端 后端 概述 本模块主要完成对图书的借阅处理。需要实现三个接口&#xff0c;第一个是获取所有的读者的借阅卡号&#xff0c;第二个是获取所有的未被借阅的图书编号&#xff0c;第三…

Spring Boot 启动注解分析

文章目录 1. SpringBootApplication2. EnableAutoConfiguration3. AutoConfigurationImportSelector3.1 isEnabled3.2 getCandidateConfigurations 3.3 removeDuplicates3.4 getExclusions3.5 checkExcludedClasses3.6 removeAll3.7 filter 虽然我们在日常开发中&#xff0c;S…

【Golang】golang中http请求的context传递到异步任务的坑

文章目录 前言一、HTTP请求的Context传递到异步任务的坑 前言 在golang中&#xff0c;context.Context可以用来用来设置截止日期、同步信号&#xff0c;传递请求相关值的结构体。 与 goroutine 有比较密切的关系。 在web程序中&#xff0c;每个Request都需要开启一个goroutin…

使用docker部署nginx并支持https

配置nginx支持https&#xff0c;其实也简单&#xff0c;搞个证书&#xff0c;然后修改下配置文件就好了。我以前一篇文章&#xff08;使用docker部署多个nginx站点并配置负载均衡&#xff09;为例&#xff0c;做个记录。 如前所述&#xff0c;我使用docker&#xff0c;部署了3…