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实现简单的可逆加密程序实例
Mar 05 Python
Python中查看文件名和文件路径
Mar 31 Python
Python基础学习之常见的内建函数整理
Sep 06 Python
DataFrame 将某列数据转为数组的方法
Apr 13 Python
Python批量删除只保留最近几天table的代码实例
Apr 01 Python
Python绘制股票移动均线的实例
Aug 24 Python
Python如何使用字符打印照片
Jan 03 Python
python字符串判断密码强弱
Mar 18 Python
python实现一次性封装多条sql语句(begin end)
Jun 06 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
Aug 18 Python
pycharm 2020 1.1的安装流程
Sep 29 Python
Python环境使用OpenCV检测人脸实现教程
Oct 19 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 mysql索引问题
2008/06/07 PHP
php cookie 登录验证示例代码
2009/03/16 PHP
PHP MySQL应用中使用XOR运算加密算法分享
2011/08/28 PHP
php文件操作实例代码
2012/05/10 PHP
分享一段PHP制作的中文拼音首字母工具类
2014/12/11 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
2017/09/16 PHP
表格 隔行换色升级版
2009/11/07 Javascript
js验证是否为数字的总结
2013/04/14 Javascript
jQuery统计上传文件大小的方法
2015/01/24 Javascript
JavaScript控制按钮可用或不可用的方法
2015/04/03 Javascript
js console.log打印对像与数组用法详解
2016/01/21 Javascript
Vue2.5通过json文件读取数据的方法
2018/02/27 Javascript
JavaScript实现图片懒加载的方法分析
2018/07/05 Javascript
详解angular应用容器化部署
2018/08/14 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
js实现轮播图效果 纯js实现图片自动切换
2020/08/09 Javascript
简单实现python爬虫功能
2015/12/31 Python
利用Python对文件夹下图片数据进行批量改名的代码实例
2019/02/21 Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
2020/03/31 Python
Python使用monkey.patch_all()解决协程阻塞问题
2020/04/15 Python
在python中使用nohup命令说明
2020/04/16 Python
django创建超级用户时指定添加其它字段方式
2020/05/14 Python
如何理解python中数字列表
2020/05/29 Python
HTML5是什么 HTML5是什么意思 HTML5简介
2012/10/26 HTML / CSS
html5 Canvas画图教程(3)—canvas出现1像素线条模糊不清的原因
2013/01/09 HTML / CSS
美国最大的香水出口:FragranceX.com
2017/11/04 全球购物
G-Form护具官方网站:美国运动保护装备
2019/09/04 全球购物
技校毕业生个人学习的自我评价
2014/02/21 职场文书
信息技术培训感言
2014/03/06 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
应届大学生自荐书
2014/06/17 职场文书
党员对照检查材料思想汇报
2014/09/16 职场文书
校园新闻广播稿5篇
2014/10/10 职场文书
2016入党培训心得体会范文
2016/01/08 职场文书
python 自动刷新网页的两种方法
2021/04/20 Python
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/06 PostgreSQL