浮点型在内存中的存储 浮点型如何取出 IEEE754 SME 精度丢失 C语言进阶

2023-10-23 13:50

本文主要是介绍浮点型在内存中的存储 浮点型如何取出 IEEE754 SME 精度丢失 C语言进阶,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者的话
本文涵盖了浮点型在内存中的如何存储、如何取出、为何有精度丢失等知识点~


浮点型概括

常见的浮点型数据有三种:

  1. 以科学计数法表示的:1e10、1.28e10
  2. 数据后加入字符‘f’的:3.14f、7.76f
  3. 不用科学计数法也不加f:1.22、4.89

第一种表示:
1*10^10 和 1.28*10^10
第二种表示:
用float创建的浮点数,要在后面加’f’,不然会默认为double型储。
第三种表示:
用double创建的浮点数,或没加‘f’的float创建数。


浮点数的存储

根据国际标准IEEE754规定,任意的浮点数V都可以表示为以下形式:

  • V=(-1)^S * M * 2^E
  • S等于0或1,是-1的指数位,0则正数,1则负数
  • M等于有效数字,应大于1,小于2
  • E是2的指数位,是一个有范围的正数

例:

  1. V=5.5
  2. V=9.0

首先我们要知道,十进制的小数点右边第一位,表示10的-1次方,同样,二进制的小数点后一位,是表示2的-1次方
则V=5.5可以分解成:101.1
则V=9.0可以分解成:1001.0
随后,将这个分解后的数字转为大于1,小于2的数,并将小数点移动了几位记下来,这将是E的大小

  1. V=1.011,移动2位,E=2
  2. V=1.001,移动3位,E=3

最后,如果是正数,S为0,如果是负数,S为1。

  1. V=(-1)^0 * 1.011 * 2^2
  2. V=(-1)^0 * 1.001 * 2^3

这样,你就知道如何表示一个浮点型的数了,由此可见,一个浮点型的数,其大小只与>S、M、E三个变量有关,所以在内存中对于浮点型的存储,只需要存储这三个变量可。


bit位储存模型

在这里插入图片描述
在这里插入图片描述

  • 第一张图:float的储存模型
  • 第二张图:double的储存模型
  • 图片来自比特科技

这两张图相信以各位的聪明才智,不需过多解释也能看得懂。

我们知道,M是一个大于1,小于2的数,那么不同的M之间只有小数点后面的数不同,如果我们只把M小数点后面的数存起来,取出的时候再加上1,就可以多存一位。
因此,float的M能存24位,double的M能存53位。

此外,对于E的存储,还有一些别的规定:

因为E是一个无符号的数,只能是正数,但是科学计数法中是可以出现负数的,所以IEEE又规定,E在存入时必须加上一个中间值

  • 对于float,E有8位,取值范围为0~255,存入时需加上255/2=127.
  • 对于double,E有11位,取值范围为0~2047,存入时需加上2047/2=1023.

比如:5.5的E是2,存入时需存2+127=129;9.0的E是3,存入时需存3+127=130.


精度丢失

上述我们说到,二进制小数点后1位是2的-1次方,后2位是2的-2次方…

即,一个浮点型的小数点后面的数,只能用0.5、0.25、0.125…等等数来拼凑起来。

若是我给一个3.141592653579,这在有限的M位下是不可能完整精确地拼凑起来的,于是就有了精度丢失
在这里插入图片描述
Look:我把3.14存进a,鼠标放在上面,显示这个数并不是精准的3.14.

这也是为什么,double型能存的数据比float型更为精准。(因为M位更多)


浮点型的取出

  • S的取出:没什么好说的,是1还是1,是0还是0.
  • M的取出:因为只存了小数点后面,取出来后要加上1.
  • E的取出:又分为三种情况,请看细细道来。

1,E全为1,此时若M全是0,则是无穷大,正负看S;若M不全是0,则这个数是NaN(未定义或不可表示的值),至于为什么,我只能说这是未尽事宜,是规定。

2,E全为0,这种情况下在取出E时,float规定E为-126,double规定E为-1022,M取出来后不再加上1,以此来表示一个无限接近于0的数,正负看S。

3,E不全0也不全1,减去127或1023拿出来即可。


浮点数的取出实机演示

在这里插入图片描述
如图,我将5.5f存入a;
在这里插入图片描述
随后,取a的地址进行观察。
因为我当前环境是x86,机器为小端存储。

PS:如果您不明白什么是小端存储,请点击:大小端字节序存储详解

所以a的地址存放的十六进制序列为:40B00000
转换为二进制:0 10000001 01100000000000000000000
观察S、M、E的位置
S:0
E:因为不全是1或全是0,应减去127,0b10000001-127=2
M:0.011+1=1.011
这样,你就把V取出来了。
这时候有同学可能要问了,这把SME三个数装上以后,是1.011*2^2是4.011啊。

请注意:此时是用二进制表示


这篇关于浮点型在内存中的存储 浮点型如何取出 IEEE754 SME 精度丢失 C语言进阶的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/2301_76310669/article/details/128853885
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/268266

相关文章

SpringBoot项目中Redis存储Session对象序列化处理

《SpringBoot项目中Redis存储Session对象序列化处理》在SpringBoot项目中使用Redis存储Session时,对象的序列化和反序列化是关键步骤,下面我们就来讲讲如何在Spri... 目录一、为什么需要序列化处理二、Spring Boot 集成 Redis 存储 Session2.1

Java内存区域与内存溢出异常的详细探讨

《Java内存区域与内存溢出异常的详细探讨》:本文主要介绍Java内存区域与内存溢出异常的相关资料,分析异常原因并提供解决策略,如参数调整、代码优化等,帮助开发者排查内存问题,需要的朋友可以参考下... 目录一、引言二、Java 运行时数据区域(一)程序计数器(二)Java 虚拟机栈(三)本地方法栈(四)J

基于MongoDB实现文件的分布式存储

《基于MongoDB实现文件的分布式存储》分布式文件存储的方案有很多,今天分享一个基于mongodb数据库来实现文件的存储,mongodb支持分布式部署,以此来实现文件的分布式存储,需要的朋友可以参考... 目录一、引言二、GridFS 原理剖析三、Spring Boot 集成 GridFS3.1 添加依赖

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

$在R语言中的作用示例小结

《$在R语言中的作用示例小结》在R语言中,$是一个非常重要的操作符,主要用于访问对象的成员或组件,它的用途非常广泛,不仅限于数据框(dataframe),还可以用于列表(list)、环境(enviro... 目录1. 访问数据框(data frame)中的列2. 访问列表(list)中的元素3. 访问jav