浮点数在计算机内存中的存储方式

本文深入探讨了浮点数在计算机中的表示方法,解释了为何浮点运算会出现精度丢失的问题。通过详细分析十进制小数转二进制的过程,以及浮点数在内存中的科学计数法存储原理,揭示了指数位引入偏移量的重要性和原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
以前刚开始学习的时候有听老师说过两个浮点数相加会出现精度丢失的现象,那时候不理解原因,只是作为一个知识记下来,最近在工作中也遇到了同样的问题,于是想研究下底层的原因。

十进制小数如何转为二进制

我们知道在计算机中,所有数据都是以二进制0和1来存储的,那么我们十进制的小数是如何用二进制形式表示的呢?
答案是采用"乘2取整,顺序排列"法,即将小数部分乘以2,然后取整数部分,剩下的小数部分继续乘以2,然后取整数部分,剩下的小数部分又乘以2,一直取到小数部分全部为零结束(有可能遇到乘不尽而不停循环的情况出现)。
举例十进制数0.9

0.9*2=1.8     取整数部分 1
0.8*2=1.6     取整数部分 1
0.6*2=1.2     取整数部分 1
0.2*2=0.4     取整数部分 0
0.4*2=0.8     取整数部分 0
0.8*2=1.6     取整数部分 1
0.6*2=1.2     取整数部分 0
.........

十进制数0.9的二进制数为(从上往下): 0.11100110011001…
(这里我们只是从纯数学的角度去换算,暂不考虑计算机的角度,实际上计算机中只有01连小数点都没有,计算机该怎么确定小数点的位置这个问题我们后面在解释)

以上是整数位本来为0的情况,那如果整数位本来不为0的话,比如9.9,我们需要对整数部分和小数部分分别用不同的转换法,整数部分我们用"除2取余,逆序排列"法,计算得9的二进制数是1001,小数部分我们按照前面的方法算得0.11100110011001…,所以两部分相加得1001.11100110011001…

由此可见,很多10进制的小数,转为二进制后,就变成无限循环小数了,而且计算机中存储一个浮点数所用的位数也是有限的,所以只能选择在某一个精度进行保存。这也就解释了为什么浮点型加减法出现了的精度丢失问题。

浮点型在内存中的存储

从上面我们知道了十进制如何转换为二进制,但是二进制浮点数又是怎么保存在内存中的呢,要知道计算机中只有01可没有小数点,那么浮点数的小数点位置又是怎么保存的呢?
聪明的计算机科学家们想到了用二进制的科学计数法来解决这个问题,例如:十进制5.5,其二进制数为101.1,用二进制的科学计数法可以表示为 1.011 × 2 2 1.011 \times 2^2 1.011×22,任何一个二进制数字的科学计数法都可以表示为 1. x x x × 2 n 1.xxx \times2^n 1.xxx×2n。这样一来,我们就将小数点的位置信息转换到了2的指数上。

我们在计算机中只要保存以下三部分信息:

  1. 符号位(Sign):0代表正,1代表负
  2. 指数位(Exponent):用于存储科学计数法中的指数数据
  3. 位数部分(Mantissa): 1. x x x × 2 n 1.xxx\times2^n 1.xxx×2n 的xxx部分

其中float的存储方式如下图所示:
在这里插入图片描述
double的存储方式为
在这里插入图片描述
由于二进制的科学计数法 1. x x x × 2 n 1.xxx\times2^n 1.xxx×2n 第一位永远是1,所以在计算机中我们只保留小数点后面的数,即尾数。比如保存1.011的时候只保存011,等到读取的时候再把第一位1加上去。这样做的目的是节省一位有效数字,以32位浮点数为例,留给M只有23位,将第一位舍去后,就能多保存一位小数精度,对于一些无限不循环小数,这么做的意义是重大的。

至于指数E,情况比较复杂。
因为指数是可正可负的,8位的指数位能表示的取值范围应该为-127 ~ 128,11位的指数位能表示的取值范围应该为-1023 ~ 1024,但是IEEE(国际电气协会) 规定指数的真实值要加上一个偏移量,对于8位的E,这个偏移量是127,对于11位的E,这个偏移量是1023。这样一来,8位的E取值范围就变成了0 ~ 255,而11位的E取值范围就变成了0 ~2047。为什么指数位要加上偏移量而不用指数原本的真实值呢,这是因为正数和负数之间大小比较不如无符号数方便,具体原因我们放在后面分析。

我们以float类型5.5为例:

  1. 将5.5转为二进制数是101.1
  2. 将101.1转为科学计数法 1.011 × 2 2 1.011\times2^2 1.011×22
  3. 指数2加上偏移量127等于129,转为二进制为1000 0001

最终存储在计算机中的数据如下
在这里插入图片描述

指数位为什么要引入偏移量

纯无符号数有什么好处呢?在很多情况下处理更方便。要知道 在计算机底层 加减乘 最终都是转为加法的。
我们假设不引入偏移量,那就要用正负数来表示指数值了。
负数的原码,反码,补码比它绝对值的原码,反码,补码要大。
假如有两个浮点数,尾数部分相同,浮点数a的指数为-2,浮点数b的指数为2。
当直接比较两个浮点数指数大小时,会用一个1xxxxxx 来跟一个0xxxxxxx来比较。
这明显不是人类想要的结果。如果引入偏移量127,就会变成 127+(-2) 与127+2之间的比较.这样的结果才是想要的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值