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实现获取本地及远程图片大小的方法示例
Jul 21 Python
用python生成1000个txt文件的方法
Oct 25 Python
Django开发的简易留言板案例详解
Dec 04 Python
python使用response.read()接收json数据的实例
Dec 19 Python
python脚本之一键移动自定格式文件方法实例
Sep 02 Python
Python lambda表达式filter、map、reduce函数用法解析
Sep 11 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
详解用Python调用百度地图正/逆地理编码API
Jul 02 Python
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
Mar 29 Python
python tkinter Entry控件的焦点移动操作
May 22 Python
python3操作redis实现List列表实例
Aug 04 Python
python人工智能human learn绘图可创建机器学习模型
Nov 23 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
一次编写,随处运行
2006/10/09 PHP
C# Assembly类访问程序集信息
2009/06/13 PHP
PHP日期处理函数 整型日期格式
2011/01/12 PHP
PHP数组及条件,循环语句学习
2012/11/11 PHP
使用Discuz关键词服务器实现PHP中文分词
2014/03/11 PHP
Zend Framework教程之Zend_Registry对象用法分析
2016/03/22 PHP
在Laravel框架里实现发送邮件实例(邮箱验证)
2016/05/20 PHP
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
移动端 一个简单易懂的弹出框
2016/07/06 Javascript
Javascript 正则表达式校验数字的简单实例
2016/11/02 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
Angular4表单验证代码详解
2017/09/03 Javascript
jQuery与vue实现拖动验证码功能
2018/01/30 jQuery
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
jQuery实现简单评论区功能
2020/10/26 jQuery
[10:53]2018DOTA2国际邀请赛寻真——EG
2018/08/11 DOTA
Python设计模式之观察者模式实例
2014/04/26 Python
Python 抓取动态网页内容方案详解
2014/12/25 Python
Python实现购物车程序
2018/04/16 Python
对numpy中array和asarray的区别详解
2018/04/17 Python
pandas删除指定行详解
2019/04/04 Python
python pillow模块使用方法详解
2019/08/30 Python
在python中list作函数形参,防止被实参修改的实现方法
2020/06/05 Python
Python趣味入门教程之循环语句while
2020/08/26 Python
python中spy++的使用超详细教程
2021/01/29 Python
CSS3的颜色渐变效果的示例代码
2017/09/29 HTML / CSS
J.Crew官网:美国知名休闲服装品牌
2017/05/19 全球购物
英国在线发型和美容产品商店:Beauty Cutie
2019/04/27 全球购物
研究生毕业鉴定
2014/01/29 职场文书
统计学教授推荐信
2014/09/18 职场文书
2015年度学校卫生工作总结
2015/05/12 职场文书
2015年客房服务员工作总结
2015/05/15 职场文书
高中升旗仪式主持词
2015/07/03 职场文书
教你用python实现一个无界面的小型图书管理系统
2021/05/21 Python
Golang入门之计时器
2022/05/04 Golang
Python使用openpyxl模块处理Excel文件
2022/06/05 Python