文档章节

Python 浮点数运算

rainyear
 rainyear
发布于 2016/05/12 04:31
字数 1021
阅读 110
收藏 7

浮点数用来存储计算机中的小数,与现实世界中的十进制小数不同的是,浮点数通过二进制的形式来表示一个小数。在深入了解浮点数的实现之前,先来看几个 Python 浮点数计算有意思的例子:

0.1 == 0.10000000000000000000001
True
0.1+0.1+0.1 == 0.3
False

IEEE 浮点数表示法

这些看起来违反常识的“错误”并非 Python 的错,而是由浮点数的规则所决定的,即使放到其它语言中结果也是这样的。要理解计算机中浮点数的表示规则,先来看现实世界中十进制小数是如何表示的:

1.234 = 1 + 1/10 + 2/100 + 3/1000

可以用下面的公式来表示:

$$d = \sum_{i=-n}^m10^i*d_i$$

其中 $d_i$ 是十进制中 0~9 的数字。而如果是一个二进制的小数:

1.001 = 1 + 0/2 + 0/4 + 1/8

可以用下面的公式来表示:

$$d = \sum_{i=-n}^m2^i*d_i$$

其中 $d_i$ 是二进制中的 0 或 1。Python 中的浮点数都是双精度的,也就说采用 64 位来表示一个小数,那这 64 位分别有多少用来表示整数部分和小数部分呢?根据 IEEE 标准,考虑到符号位,双精度表示法是这样分配的:

$$d = s * \sum_{i=-52}^{11} 2^i*d_i$$

也就是说用1位表示符号位,11位表示整数部分,52位表示小数部分。正如十进制中我们无法精确表示某些分数(如10/3),浮点数中通过 d1/2 + d2/4 + ... 的方式也会出现这种情况,比如上面的例子中,十进制中简单的 0.1 就无法在二进制中精确描述,而只能通过近似表示法表示出来:

(0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)

也就是说 0.1 是通过 3602879701896397/36028797018963968 来近似表示的,很明显这样近似的表示会导致许多差距很小的数字公用相同的近似表示数,例如:

(0.10000000000000001).as_integer_ratio()
(3602879701896397, 36028797018963968)

在 Python 中所有这些可以用相同的近似数表示的数字统一采用最短有效数字来表示:

print(0.10000000000000001)
0.1

浮点数运算

既然有些浮点数是通过近似值表示的,那么在计算过程中就很容易出现误差,就像最开始的第二个例子一样:

a = .1 + .1 + .1
b = .3
print(a.as_integer_ratio())
print(b.as_integer_ratio())
print(a == b)
(1351079888211149, 4503599627370496)
(5404319552844595, 18014398509481984)
False

为了解决运算中的问题,IEEE 标准还指定了一个舍入规则(round),即 Python 中内置的 round 方法,我们可以通过舍入的方式取得两个数的近似值,来判断其近似值是否相等:

round(a, 10) == round(b, 10)
True

当然这种舍入的方式并不一定是可靠的,依赖于舍入的选择的位数,位数太大,就失去了 round 的作用,太小,就会引入别的错误:

print(round(a, 17) == round(b, 17))
print(round(0.1, 1) == round(0.111, 1))
False
True

Python 中使用更精确的浮点数可以通过 decimalfractions 两个模块,从名字上也能猜到,decimal 表示完整的小数,而 fractions 通过分数的形式表示小数:

from decimal import Decimal
a = Decimal(0.1)
b = Decimal(0.1000000000000001)
c = Decimal(0.10000000000000001)
print(a)
print(b)
print(c)

a == b == c
0.1000000000000000055511151231257827021181583404541015625
0.10000000000000010269562977782697998918592929840087890625
0.1000000000000000055511151231257827021181583404541015625





False
from fractions import Fraction
f1 = Fraction(1, 10) # 0.1
print(float(f1))
f3 = Fraction(3, 10) # 0.3
print(float(f3))

print(f1 + f1 + f1 == f3)
0.1
0.3
True

总结

浮点数这些奇特的特性让我们不得不在使用的时候格外注意,尤其是当有一定的精度要求的情况下。如果真的是对精度要求较高且需要频繁使用浮点数,建议使用更专业的 SciPy 科学计算包。


pyhub

© 著作权归作者所有

共有 人打赏支持
rainyear
粉丝 3
博文 9
码字总数 10955
作品 0
杭州
CTO(技术副总裁)
Python基础---数据类型和变量

数据类型 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数...

wuli03960405
06/26
0
0
人人都能学会的python编程教程2:数据类型和变量

数据类型 了解一门编程语言最开始就是了解它的数据类型了,python基本的数据类型分为如下几类: 整数 Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模...

编程老司机
05/10
0
0
Python全栈工程师(数值类型、运算符)

ParisGabriel Python 入门基础 python的应用领域: 1.系统运维 2.网络编程(如:网络爬虫,搜索引擎,服务器编程) 3.科学计算 4.航空领域(如:卫星,导弹,等) 5.人工智能,机器人 6.web开...

巴黎香榭
07/02
0
0
[雪峰磁针石博客]python3快速入门教程9重要的标准库-高级篇

[雪峰磁针石博客]python3快速入门教程 输出格式 reprlib模块为大型的或深度嵌套的容器提供了缩写显示的repr(): pprint提供显示更好的print。 textwrap模块格式化文本段落以适应设定的屏宽: l...

Python测试开发人工智能
06/20
0
0
python核心编程-第五章-个人笔记

简介 ①Python中数字支持以下类型:整型、长整型、布尔型、双精度浮点型、十进制浮点型和复数 ②创建数字对象和给变量赋值一样】 ③用del删除对对象的引用。删除之后,无法再使用这个引用(变...

好好先生_1028
2015/11/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
0
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
2
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部