python中实现精确的浮点数运算详解


Posted in Python onNovember 02, 2017

为什么说浮点数缺乏精确性?

在开始本文之前,让我们先来谈谈浮点数为什么缺乏精确性的问题,其实这不是Python的问题,而是实数的无限精度跟计算机的有限内存之间的矛盾。

举个例子,假如说我只能使用整数(即只精确到个位,计算机内的浮点数也只有有限精度,以C语言中的双精度浮点数double为例,精度为52个二进制位),要表示任意实数(无限精度)的时候我就只能通过舍入(rounding)来近似表示。

比如1.2我会表示成1,2.4表示成2,3.6表示成4.

所以呢?

在算1.2 - 1.2的时候,由于计算机表示的问题,我算的实际上是1 - 1,结果是0,碰巧蒙对了;

在算1.2 + 1.2 - 2.4的时候,由于计算机表示的问题,我算的实际上是1 + 1 - 2,结果是0,再次蒙对了;

但是在算1.2 + 1.2 + 1.2 - 3.6的时候,由于计算机表示的问题,我算的实际上是1 + 1 + 1 - 4,结果是-1,运气没那么好啦!

这里的1.2, 2.4, 3.6就相当于你问题里的0.1, 0.2和0.3,1, 2, 4则是真正在计算机内部进行运算的数值,我说清楚了吗?

其他请看IEEE 754浮点数标准,比如CSAPP第二章啥的(虽然估计你没兴趣看)。

另:不仅仅是浮点数的在计算机内部的表示有误差,运算本身也可能会有误差。比如整数2可以在计算机内准确表示,但是要算根号2就有误差了;再比如两个浮点数相除,本来两个数都是精确表示的,但除的结果精度却超出了计算机内实数的表示范围,然后就有误差了。

好了,下面话不多说了,开始本文的正文:

起步

浮点数的一个普遍的问题是它们不能精确的表示十进制数。

>>> a = 4.2
>>> b = 2.1
>>> a + b
6.300000000000001
>>> (a + b) == 6.3
False
>>>

这是由于底层 CPU 和IEEE 754 标准通过自己的浮点单位去执行算术时的特征。看似有穷的小数, 在计算机的二进制表示里却是无穷的。

一般情况下,这一点点的小误差是允许存在的。如果不能容忍这种误差(比如金融领域),那么就要考虑用一些途径来解决这个问题了。

Decimal

使用这个模块不会出现任何小误差。

>>> from decimal import Decimal
>>> a = Decimal('4.2')
>>> b = Decimal('2.1')
>>> a + b
Decimal('6.3')
>>> print(a + b)
6.3
>>> (a + b) == Decimal('6.3')
True

尽管代码看起来比较奇怪,使用字符串来表示数字,但是 Decimal 支持所有常用的数学运算。 decimal 模块允许你控制计算的每一方面,包括数字位数和四舍五入。在这样做之前,需要创建一个临时上下文环境来改变这种设定:

>>> from decimal import Decimal, localcontext
>>> a = Decimal('1.3')
>>> b = Decimal('1.7')
>>> print(a / b)
0.7647058823529411764705882353
>>> with localcontext() as ctx:
...  ctx.prec = 3
...  print(a / b)
...
0.765
>>> with localcontext() as ctx:
...  ctx.prec = 50
...  print(a / b)
...
0.76470588235294117647058823529411764705882352941176
>>>

由于 Decimal 的高精度数字自然也就用字符串来做展示和中转。

总结

总的来说,当涉及金融领域时,哪怕是一点小小的误差在计算过程中都是不允许的。因此 decimal 模块为解决这类问题提供了方法。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python解析网页源代码中的115网盘链接实例
Sep 30 Python
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
May 05 Python
Python实现图片转字符画的示例代码
Aug 21 Python
python绘制铅球的运行轨迹代码分享
Nov 14 Python
python 删除列表里所有空格项的方法总结
Apr 18 Python
Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS浅析
May 08 Python
Win10+GPU版Pytorch1.1安装的安装步骤
Sep 27 Python
Django操作session 的方法
Mar 09 Python
Python-jenkins模块获取jobs的执行状态操作
May 12 Python
python爬虫分布式获取数据的实例方法
Nov 26 Python
Python实现生活常识解答机器人
Jun 28 Python
Python开发五子棋小游戏
May 02 Python
利用Python-iGraph如何绘制贴吧/微博的好友关系图详解
Nov 02 #Python
python3.0 模拟用户登录,三次错误锁定的实例
Nov 02 #Python
Python安装Numpy和matplotlib的方法(推荐)
Nov 02 #Python
Python 多进程并发操作中进程池Pool的实例
Nov 01 #Python
python 3.0 模拟用户登录功能并实现三次错误锁定
Nov 01 #Python
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
Nov 01 #Python
Python编程实现双链表,栈,队列及二叉树的方法示例
Nov 01 #Python
You might like
php下封装较好的数字分页方法
2010/11/23 PHP
php实现有序数组打印或排序的方法【附Python、C及Go语言实现代码】
2016/11/10 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
php数组指针函数功能及用法示例
2020/02/11 PHP
基于PHP的微信公众号的开发流程详解
2020/08/07 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
收藏Javascript中常用的55个经典技巧
2007/08/12 Javascript
Jquery优化效率 提升性能解决方案
2010/09/06 Javascript
基于JQuery的简单实现折叠菜单代码
2010/09/15 Javascript
Javascript继承(上)——对象构建介绍
2012/11/08 Javascript
关于Javascript与iframe的那些事儿
2013/07/04 Javascript
javascript中自定义对象的属性方法分享
2013/07/12 Javascript
JavaScript中变量声明有var和没var的区别示例介绍
2014/09/15 Javascript
JavaScript通过事件代理高亮显示表格行的方法
2015/05/27 Javascript
纯javascript判断查询日期是否为有效日期
2015/08/24 Javascript
关于动态生成dom绑定事件失效的原因及解决方法
2016/08/06 Javascript
AngularJS入门教程之静态模板详解
2016/08/18 Javascript
JavaScript函数节流和函数防抖之间的区别
2017/02/15 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
2019/05/05 Javascript
vue实现中部导航栏布局功能
2019/07/30 Javascript
手写Vue2.0 数据劫持的示例
2021/03/04 Vue.js
python中的sort方法使用详解
2014/07/25 Python
Python网络爬虫神器PyQuery的基本使用教程
2018/02/03 Python
python2.7实现FTP文件下载功能
2018/04/15 Python
python中调试或排错的五种方法示例
2019/09/12 Python
解决ROC曲线画出来只有一个点的问题
2020/02/28 Python
python获取时间戳的实现示例(10位和13位)
2020/09/23 Python
HTML5上传文件显示进度的实现代码
2012/08/30 HTML / CSS
幼儿园实习自我鉴定
2013/12/15 职场文书
大课间体育活动方案
2014/03/12 职场文书
道路交通事故赔偿协议书
2014/10/24 职场文书
2014年计划生育工作总结
2014/11/14 职场文书
2015年医院工作总结范文
2015/04/09 职场文书
MySQL连表查询分组去重的实现示例
2021/07/01 MySQL
大脑的记忆过程在做数据压缩,不同图形也有共同的记忆格式
2022/04/29 数码科技