[转]浮点数解惑

注:文章中涉及的运算的结果,通过http://babbage.cs.qc.edu/IEEE-754/Decimal.html进行验证

在我们编程的时候经常会涉及到浮点数。 而且你会奇怪的发现 0.1+0.2==0.3的逻辑值为false,你知道这是为什么么?

使用python直接计算得到的结果是0.30000000000000004 这其实涉及到浮点数在计算机中的表示方法,舍入的方式,以及如何进行数学运算等问题。

一.十进制转二进制

首先看下十进制的浮点数如何通过二进制的方式来表示. 比如3.6如果使用二进制的方式来进行表示应该如何做呢? 我们可以将整数和小数分开进行。 对于整数部分我们可以使用“除二取余,倒序排列”法来进行。

3除以2 上1余1
1除以2 上0余1
所以3使用二进制表示就是11

小数部分“乘二取整,顺序排列”法来进行

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 1 从这里开始1001循环

所以3.6使用二进制进行表示的话就是11.100110011001….(1001循环)

二.IEEE754标准

1.IEEE 754 存储格式

在计算机里表示一个数字可没有像我们在纸上写上一个阿拉伯数字那么简单。 目前的计算机能够认识的就是0101,所以我们的数得转换成二进制表示,但同时数有正负,所以一般有一个符号位的概念。 那么浮点数呢?我们知道浮点数可以使用科学计数法来进行表示(在科学记数法中,一个数被写成一个1与10之间的实数(尾数)与一个10的幂(指数)的积,为了得到统一的表达方式,该尾数并不包括10)。 类似,二进制的浮点数也可以写成类似十进制的科学计数的形式,只不过底数不是10,而是2了。 比如 0.00101可以表示成1.01X2-3
现在我们来正式谈谈IEEE 754标准了,

一个按照IEEE 754标准表示的浮点数一般由一位符号位,m位指数(注意,实际存储的是真实指数值加上2m-1 之后的值,因为为了方便指数的对其比较,不加的话,指数有正有负比较起来不方便),n位尾数组成(由于尾数在存储的时候其整数位上都规定为1,所以为了节省空间,这个整数位上的1就省去了),且高位在左低位在右.

常见的C或者Java语言,都实现了IEEE 754的浮点数标准。 比如C或者Java中的float和double分别对应单精度浮点数和双精度浮点数,这两类表示的方式相同,不同的只是指数和尾数的位数不一样而已。 单精度浮点数由32位二进制位组成(四个字节),其中1位符号位,8位指数位,23位尾数位。

双精度浮点数由64位二进制位组成(八个字节),其中1位符号位,11位指数位,52位尾数位。

2.舍入规则

IEEE 754-1985 中提及了四种舍入规则

  • 舍入到最接近,在一样接近的情况下偶数优先(Ties To Even)(这是默认的舍入方式):会将结果舍入为最接近且可以表示的值,但是当存在两个数一样接近的时候,则取其中的偶数(在二进制中式以0结尾的)
  • 向+∞方向舍入:会将结果朝正无限大的方向舍入。
  • 向-∞方向舍入: 会将结果朝负无限大的方向舍入。
  • 向0方向舍入: 会将结果朝0的方向舍入。

对于第一种舍入规则,有必要详细的说明下。 在十进制中比如0.45 按照第一个规则保留小数点后面一位小数进行舍入的话,就应该为0.4 因为0.45和0.4和0.5的距离一样,但是4为偶数,所以取0.4. (对于这部分你可以在大脑中想象出一根数轴来)
对于二进制数来说也一样,比如有这样的一个二进制表示的数 0.1011
如果想保留小数点后面一位,发现后一位之后为011,很显然0.1011距离0.1近,距离1.0远,所以后面的011果断舍去得到0.1
但是如果需要保留小数点后面两位,发现两位之后是11,很显然0.1011距离0.11更近,所以果断进位,得到0.11
如果保留小数点后3位,这个时候问题来了,因为0.1011和0.101,0.110的距离相等,但是由于0.110末位为偶,所以得到0.110

三.问题解析

现在我们来看看开始说的0.1+0.2为什么不等于0.3的问题 在Python中浮点数是64位双精度浮点数,相当于C语言中的double

0.1在计算机中如何表示的呢?

0.1X2=0.2 0
0.2X2=0.4 0
0.4X2=0.8 0
0.8X2=1.6 1
0.6X2=1.2 1
0.2X2=0.4 0 开始0011循环

所以0.1的二进制为
0.00011001100110011001100110011….
现在将其表示为IEEE 754 浮点数的形式
0.1是正数,符号位为0
0.00011001100110011…=1.100110011001…X2-4
所以其指数是-4,加上1023就是1019,1019的二进制值是01111111011
剩下的就是尾数部门了,去除首尾的整数部分,末尾待舍去的是1001…所以需要向前进一位
0011111110111001100110011001100110011001100110011001100110011010
同理可以得到0.2的IEEE 754的格式为(其中指数为-3,填入的时候是-3+1023=1020)
0011111111001001100110011001100110011001100110011001100110011010
两个数相加,这个时候发现指数不一致,所以需要对齐,一般情况下是向右移,因为最右边的即使溢出了,损失的精度远远小于左边溢出。
所以这个时候指数的真正的值都为-3,然后0.1右移后的尾数与0.2的尾数进行相加(别忘记首位的1)
这个时候尾数相加

 0.1100110011001100110011001100110011001100110011001101  
+1.1001100110011001100110011001100110011001100110011010
--------------------------------------------------------
10.0110011001100110011001100110011001100110011001100111
规格化之后(注意末尾有进位)
为1.0011001100110011001100110011001100110011001100110100X2^(-2)  

0011111111010011001100110011001100110011001100110011001100110100
其化成十六进制的表示为3FD3333333333334
通过在线的求值工具http://babbage.cs.qc.edu/IEEE-754/64bit.html可以求得,其值为0.30000000000000004
而0.3在计算机中的格式为
0011111111010011001100110011001100110011001100110011001100110011
化成十进制为
0.29999999999999999
所以说造成0.1+0.2!=0.3的根本原因在于舍入上。0.1和0.2在舍入的时候都是进位,而0.3没有进位,所以0.3<0.1+0.2

四.其他

如果当我们数值计算的精度超出了IEEE 754所能表达的范围的时候,我们应该怎么办呢?为了满足这个需求,一般在高级语言中都有软件的方式实现,比如Java中的BigDecimal。
在经济、金融和与人相关的程序中,建议使用十进制浮点数。但是,由于没有硬件支持,用软件实现的十进制浮点计算比硬件实现的二进制浮点计算要慢。不过IBM公司貌似有硬件上的支持https://www.ibm.com/developerworks/wikis/display/WikiPtype/Decimal+Floating+Point

参考资料: http://en.wikipedia.org/wiki/IEEE_754-1985 http://babbage.cs.qc.edu/IEEE-754/References.xhtmlhttp://babbage.cs.qc.edu/IEEE-754/ http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

卢克  / 2011-03-31 
Published under (CC) BY-NC-SA  in categories programming   tagged with IEEE  Number 
【6层】一字型框架办公楼(含建筑结构图、计算书) 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值