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 的列表遍历删除实现代码
Apr 12 Python
python之Socket网络编程详解
Sep 29 Python
儿童python练习实例
May 27 Python
python3使用SMTP发送简单文本邮件
Jun 19 Python
Python日志模块logging基本用法分析
Aug 23 Python
Python绘制正余弦函数图像的方法
Aug 28 Python
Python for i in range ()用法详解
Sep 18 Python
如何使用python实现模拟鼠标点击
Jan 06 Python
Python实现随机生成任意数量车牌号
Jan 21 Python
Python yield的用法实例分析
Mar 06 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
Mar 25 Python
pytorch 如何使用amp进行混合精度训练
May 24 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 编写的日历
2006/10/09 PHP
通过JavaScript或PHP检测Android设备的代码
2011/03/09 PHP
php的zip解压缩类pclzip使用示例
2014/03/14 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
php查询mysql数据库并将结果保存到数组的方法
2015/03/18 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
jquery 插件开发备注
2010/08/27 Javascript
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之三
2012/01/03 Javascript
JQuery入门——用bind方法绑定事件处理函数应用介绍
2013/02/05 Javascript
JS教程:window.location使用方法的区别介绍
2013/10/04 Javascript
js通过Date对象实现倒计时动画效果
2017/10/27 Javascript
微信小程序自定义select下拉选项框组件的实现代码
2018/08/28 Javascript
React手稿之 React-Saga的详解
2018/11/12 Javascript
微信小程序实现页面跳转传递参数(实体,对象)
2019/08/12 Javascript
微信小程序如何实现点击图片放大功能
2020/01/21 Javascript
python实现百度语音识别api
2018/04/10 Python
详解Django-auth-ldap 配置方法
2018/12/10 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
2019/04/11 Python
在django中实现页面倒数几秒后自动跳转的例子
2019/08/16 Python
django orm模块中的 is_delete用法
2020/05/20 Python
tensorflow pb to tflite 精度下降详解
2020/05/25 Python
Python基于callable函数检测对象是否可被调用
2020/10/16 Python
Python 生成短8位唯一id实战教程
2021/01/13 Python
用HTML5实现网站在windows8中贴靠的方法
2013/04/21 HTML / CSS
html5实现微信打飞机游戏
2014/03/27 HTML / CSS
美国排名第一的在线葡萄酒商店:Wine.com
2016/09/07 全球购物
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
高一政治教学反思
2014/01/28 职场文书
2014元旦晚会策划方案
2014/02/19 职场文书
中学教师师德师风演讲稿
2014/08/22 职场文书
2014小学教师年度考核工作总结
2014/12/03 职场文书
事业单位个人总结
2015/02/12 职场文书
化验员岗位职责
2015/02/14 职场文书
团员自我评价范文
2015/03/10 职场文书
MySQL数据库超时设置配置的方法实例
2021/10/15 MySQL
升级 Win11 还是坚守 Win10?微软 Win11 新系统缺失功能大盘点
2022/04/05 数码科技