浮点数在内存中的存储——“C”

news2024/10/7 16:17:23

各位CSDN的uu们你们好呀,今天,小雅兰的内容是浮点数在内存中的存储,昨天我们已经写过了整型在内存中的存储,那么,浮点数在内存中是怎样存储的呢?现在,就让我们进入浮点数在内存中的存储的世界吧


常见的浮点数:

3.14159

1E10

浮点数家族包括: float、double、long double 类型。

浮点数表示的范围:float.h中定义

整型家族的类型的取值范围:limit.h


下面,我们来看一小段代码

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

 

仔细一想:打印出来的结果为什么会是这个样子呢?


浮点数存储规则

num 和 *pFloat 在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别这么大?

要理解这个结果,一定要搞懂浮点数在计算机内部的表示方法。

详细解读: 根据国际标准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.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规定:

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

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

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

前面说过, 1≤M,也就是说,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是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间 数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

 举个例子:

#include<stdio.h>
int main()
{
	float f = 5.5f;
	//101.1
	//(-1)^0*1.011*2^2
	//0 10000001 01100000000000000000000
	//   2+127
	//把二进制转化为十六进制
	//40b00000
	return 0;
}

可见,事实就是如此!


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

E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将 有效数字M前加上第一位的1。

比如:0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为:

0 01111110 00000000000000000000000

E全为0

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

1.××× * 2^-127

E全为1  

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

1.××× * 2^128

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


那么,之前的那个我们不理解的打印结果就说得通了

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

 int n = 9;

 float* pFloat = (float*)&n;

00000000000000000000000000001001 —— 9的原码

 00000000000000000000000000001001 —— 9的反码

 00000000000000000000000000001001 —— 9的补码

 0 00000000 00000000000000000001001 

 E=1-127=-126

 M=0.00000000000000000001001

 (-1)^0*0.00000000000000000001001*2^-126

显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。

*pFloat = 9.0;

1001.0

1.001*2^3

(-1)^0*1.001*2^3

S=0

M=1.001

E=3

第一位的符号位S=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130, 即10000010。

0 10000010 00100000000000000000000

    3+127

这个32位的二进制数,还原成十进制,正是 1091567616 。


好啦,小雅兰今天的内容就到这里啦,还要继续加油呀!!!

 

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

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

相关文章

超实用的公众号运营攻略分享,纯干货

很多小伙伴抱怨&#xff0c;公众号运营真的越来越难做了&#xff01; 每天会因为少得可怜的阅读量发愁&#xff0c;每天会因为纠结写什么选题发愁&#xff0c;每天更会因为公众号没有什么起色而感到无力。 现阶段公众号运营趋于饱和状态&#xff0c;公众号创建门槛低&#xf…

在Pandas中通过时间频率来汇总数据的三种常用方法

当我们的数据涉及日期和时间时&#xff0c;分析随时间变化变得非常重要。Pandas提供了一种方便的方法&#xff0c;可以按不同的基于时间的间隔(如分钟、小时、天、周、月、季度或年)对时间序列数据进行分组。 在Pandas中&#xff0c;有几种基于日期对数据进行分组的方法。我们将…

spark08-spark任务启动环境准备

内容来自尚硅谷1.submitApplication当spark执行任务时会启动java虚拟机&#xff0c;启动一个进程&#xff0c;该进程的名称为SparkSubmit&#xff0c;会执行SparkSubmit中的main方法&#xff0c;该方法中调用了super.doSubmit方法。org.apache.spark.deploy.SparkSubmitdoSubmi…

Python abs() 函数

Python abs() 函数Python 数字描述abs() 函数返回数字的绝对值。语法以下是 abs() 方法的语法:abs( x )参数x -- 数值表达式。返回值函数返回x&#xff08;数字&#xff09;的绝对值。实例以下展示了使用 abs() 方法的实例&#xff1a;#!/usr/bin/python print "abs(-45) …

百度西交大大数据菁英班目标检测竞赛

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 数据介绍 数据集共包括40000张训练图像和1000张测试图像&#xff0c;每张训练图像对应xml标注文件&#xff1a; 共包含3类&#xff1a;0:head, 1:helmet, 2:person。 提交格式要求&#xff0c;提交名为pred_r…

如何为Java文件代码签名及添加时间戳?

Java是一种流行的编程语言&#xff0c;大多数组织都使用它来开发业务应用程序。由于其高使用率&#xff0c;攻击者总是试图找到其中的漏洞并基于它利用软件。为了防止此类攻击&#xff0c; 为 Java 文件&#xff08;.jar&#xff09;进行代码签名并添加时间戳&#xff0c;可以防…

Netty网络编程实战:基于Netty的Http服务器开发

Netty网络编程实战&#xff1a;基于Netty的Http服务器开发 文章目录Netty网络编程实战&#xff1a;基于Netty的Http服务器开发介绍功能需求服务端代码实现基于Netty的WebSocket开发网页版聊天室WebSocket简介WebSocket和HTTP的区别基础环境准备服务端开发Netty中粘包和拆包的解…

关于PHP的webshell免杀小结

0X00普通的一句话木马&#xff08;适用于CTF和小站&#xff09; <?php eval($_POST[a]); ?> //函数的相似替换 <?php assert($_POST[a]); ?><?php eval($_POST[110]);?>与第一个一句话木马相比多了一个"“字符&#xff0c;我们发现这个字符的含义…

【科研】测试速通:python不同文件夹下同名图像拼接

论文必备图像拼接笔记 速通结果&#xff1a; 现有&#xff1a;测试样本相同&#xff08;名命相同&#xff09;&#xff0c;测试模型不同&#xff0c;测试结果分别保存至不同文件夹 目标&#xff1a;结果显示在同一张图像上 目录 论文必备图像拼接笔记 1.如果图像格式不一致…

怎么维护Linux VPS 服务器?简单7个步骤

维护VPS的目的是为了确保服务器网络始终畅通无阻。请注意&#xff0c;此列表中的任务并不是服务器维护所需完成的唯一任务。以下是 Linux VPS 服务器所有者可以做些什么来维护他们的服务器。 1.监控磁盘空间 服务器是个人服务器还是具有多个用户帐户的服务器并不重要&#xff0…

精简版SDL落地实践

一、前言一般安全都属于运维部下面&#xff0c;和上家公司的运维总监聊过几次一些日常安全工作能不能融入到DevOps中&#xff0c;没多久因为各种原因离职。18年入职5月一家第三方支付公司&#xff0c;前半年在各种检查中度过&#xff0c;监管形势严峻加上大领导对安全的重视(主…

【数据结构】二叉树(C语言实现)

文章目录一、树的概念及结构1.树的概念2.树的相关概念名词3.树的表示4.树在实际中的运用二、二叉树概念及结构1.二叉树的概念2.特殊的二叉树3.二叉树的性质4.二叉树的存储结构三、二叉树链式结构的实现1.结构的定义2.构建二叉树3.二叉树前序遍历4.二叉树中序遍历5.二叉树后序遍…

QWebEngineView 类 详细使用说明

文章目录 一、前言 二、详述 三、属性 四、公共函数 五、重新实现的公共函数 六、公共槽函数 七、信号 八、保护函数 九、重新实现的受保护函数 10、总结 一、前言 原文链接 QWebEngineView类提供了一个小部件&#xff0c;用于查看和编辑Web文档。 Header: #include < …

【Web安全-MSF记录篇章一】

文章目录前言msfvenom生成远控木马基本系统命令webcam 摄像头命令常用的信息收集脚本注册表设置nc后门开启 rdp&添加用户获取哈希mimikatz抓取密码前言 最近打站&#xff0c;可以感觉到之前的学的渗透知识忘记很多。。。。。多用多看多练&#xff0c;简单回顾一下 msfven…

2023年了,零基础小白转行IT学习Java还有前途吗?

“2023年了&#xff0c;转行IT学习Java是不是已经听过看过很多次了&#xff0c;Java从出现到现在有多少年了呢&#xff1f;掐指一算&#xff0c;Java是1995年由Sun公司推出的一款高级编程语言……距今已有28年了&#xff01; Sun公司都被收购了&#xff0c;莫不是Java也要垮台了…

Android实现Dribbble上动感的Gallery App Icon

先来看看原Dribbble上动感的Gallery App Icon效果图思路拆解一下&#xff0c;还是比较简单&#xff0c;需要绘制的有&#xff1a;圆形背景太阳(圆形)山(三角形)云朵(圆角矩形 三个圆)需要进行的动画&#xff1a;太阳 - 旋转动画山 - 上下平移动画云朵 - 左右平移动画不必绘制圆…

随想录二刷 (双指针法) leetcode 27 26 283 844

双指针法的原理 双指针法相对于暴力解法的优点有以下几点 暴力遍历的时间复杂度会比较高双指针法利用两个指针进行遍历完成双层循环所做的事情 双指针一般有两种方法 同向指针&#xff0c;双向指针 第一题 leetcode 27 移除元素 题目描述 题目分析 采用暴力遍历可以得出结…

vector的基本使用

目录 介绍&#xff1a; vector iterator 的使用 增删查改 增&#xff08;push_back insert&#xff09;&#xff1a; 删(pop_back erase)&#xff1a; swap&#xff1a; vector的容量和扩容&#xff1a; 排序&#xff08;sort&#xff09;&#xff1a; 介绍&#xff…

SpringBoot入门(二)

这里写目录标题一、SpringBoot整合Junit1.1 搭建SpringBoot工程1.2 引入starter-test起步依赖1.3 编写类1.4 测试二、SpringBoot整合mybatis2.1 搭建SpringBoot工程2.2 引入mybatis起步依赖&#xff0c;添加驱动2.3 编写DataSource和MyBatis相关配置2.4 定义表和实体类2.5 编写…

100%BIM学员的疑惑:不会CAD可以学Revit吗?

在新一轮科技创新和产业变革中&#xff0c;信息化与建筑业的融合发展已成为建筑业发展的方向&#xff0c;将对建筑业发展带来战略性和全局性的影响。 建筑业是传统产业&#xff0c;推动建筑业科技创新&#xff0c;加快推进信息化发展&#xff0c;激发创新活力&#xff0c;培育…