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的Flask开发框架简单上手笔记
Nov 16 Python
fastcgi文件读取漏洞之python扫描脚本
Apr 23 Python
Python单例模式的两种实现方法
Aug 14 Python
python实现俄罗斯方块游戏
Mar 25 Python
用pycharm开发django项目示例代码
Oct 24 Python
python自动发送测试报告邮件功能的实现
Jan 22 Python
Django urls.py重构及参数传递详解
Jul 23 Python
Python Django 简单分页的实现代码解析
Aug 21 Python
Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)
Feb 05 Python
Python调用.net动态库实现过程解析
Jun 05 Python
Python使用socket_TCP实现小文件下载功能
Oct 09 Python
python通配符之glob模块的使用详解
Apr 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
使用adodb lite解决问题
2006/12/31 PHP
PHP Pear 安装及使用
2009/03/19 PHP
ExtJS与PHP、MySQL实现存储的方法
2010/04/02 PHP
php生成短域名函数
2015/03/23 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势
2017/11/08 PHP
PHP简单验证码功能机制实例详解
2019/03/27 PHP
使用laravel的Eloquent模型如何获取数据库的指定列
2019/10/17 PHP
JS 容错处理代码, 屏蔽错误信息
2021/03/09 Javascript
可以将word转成html的js代码
2010/04/11 Javascript
网页中CDATA标记的说明
2010/09/12 Javascript
jQuery之选项卡的简单实现
2014/02/28 Javascript
JS清除选择内容的方法
2015/01/29 Javascript
JavaScript截断字符串的方法
2015/07/15 Javascript
jQuery实现弹窗居中效果类似alert()
2017/02/27 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
vue.js element-ui validate中代码不执行问题解决方法
2017/12/18 Javascript
JS实现图片旋转动画效果封装与使用示例
2018/07/09 Javascript
bootstrap-table formatter 使用vue组件的方法
2019/05/09 Javascript
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
vue中v-model对select的绑定操作
2020/08/31 Javascript
Python中用Descriptor实现类级属性(Property)详解
2014/09/18 Python
Python加pyGame实现的简单拼图游戏实例
2015/05/15 Python
python实现Adapter模式实例代码
2018/02/09 Python
Python实现手写一个类似django的web框架示例
2018/07/20 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
2018/11/07 Python
django admin 自定义替换change页面模板的方法
2019/08/23 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
通过一张图教会你CSS3倒影的实现
2017/09/26 HTML / CSS
幼儿老师求职信
2014/06/30 职场文书
买卖合同纠纷代理词
2015/05/25 职场文书
于丹论语心得观后感
2015/06/15 职场文书
结婚典礼致辞
2015/07/28 职场文书
《青山不老》教学反思
2016/02/22 职场文书
2016年学校爱国卫生月活动总结
2016/04/06 职场文书
大学生创业计划书常用模板
2019/08/07 职场文书