2019独角兽企业重金招聘Python工程师标准>>>

浮点数用来存储计算机中的小数,与现实世界中的十进制小数不同的是,浮点数通过二进制的形式来表示一个小数。在深入了解浮点数的实现之前,先来看几个 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.1000000000000000055511151231257827021181583404541015625False
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 科学计算包。


转载于:https://my.oschina.net/rainyear/blog/673802

Python 浮点数运算相关推荐

  1. python浮点数运算问题

    python浮点数运算问题 在python中对于一些浮点数的运算结果,往往出现一些意想不到的结果. 原因 在python中: 一个十进制数 >>>以二进制形式(近似值)存储到计算机& ...

  2. python浮点数运算问题_python基础教程之. 浮点数运算:问题和局限

    14. 浮点数运算:问题和局限¶ 浮点数在计算机硬件中表示为以 2 为底(二进制)的小数.例如,十进制小数 0.125 是1/10 + 2/100 + 5/1000 的值,同样二进制小数 0.001 ...

  3. python理解浮点数运算的误差_PyTips 0x1a - Python 浮点数运算

    版权声明:此文章转载自 Yushneng PyHub 如需转载请联系听云College团队成员阮小乙,邮箱:ruanqy#tingyun.com 本系列完整文档已托管在 Read the Docs: ...

  4. python双精度浮点数怎么写_Python双精度浮点数运算并分行显示操作示例

    本文实例讲述了Python双精度浮点数运算并分行显示操作.分享给大家供大家参考,具体如下: #coding=utf8 def doubleType(): ''''' Python中的浮点数是双精度浮点 ...

  5. python浮点数类型与数学_Python3标准库:decimal定点数和浮点数的数学运算

    1. decimal定点数和浮点数的数学运算 decimal模块实现了定点和浮点算术运算,使用的是大多数人所熟悉的模型,而不是程序员熟悉的模式(即大多数计算机硬件实现的IEEE浮点数运算).Decim ...

  6. 《Python Cookbook 3rd》笔记(3.2):执行精确的浮点数运算

    执行精确的浮点数运算 问题 你需要对浮点数执行精确的计算操作,并且不希望有任何小误差的出现. 解法 浮点数的一个普遍问题是它们并不能精确的表示十进制数.并且,即使是最简单的数学运算也会产生小的误差,比 ...

  7. python 双精度浮点_Python双精度浮点数运算并分行显示操作示例

    Python双精度浮点数运算并分行显示操作示例 这篇文章主要介绍了Python双精度浮点数运算并分行显示操作,涉及Python数学运算及显示相关操作技巧,注释备有详尽的说明,需要的朋友可以参考下 #c ...

  8. Python中关于浮点数运算的不确定尾数的解释

    一.浮点数类型 与数学中实数概念一致,带有小数点及小数的数字.浮点数取值范围和小数精度都存在限制,但常规计算可忽略. 取值范围数量级约-10308到10308,精度数量级10-16. 二.浮点数运算的 ...

  9. python减法精确度不准是什么问题,聊聊Python中的浮点数运算不准确问题

    大家好,老 Amy 来了.之前就意识到一个问题,但是最近又有朋友提出来了,所以就想着干脆记录下来,分享给大家叭~ 啥问题呢?请看题: 也就是说,需要大家计算1.1-1的值,很多朋友会说:"e ...

最新文章

  1. 2000行代码实现软渲染引擎
  2. python比前端好学吗_前端学习到底难不难?
  3. python自动化办公都能做什么菜-python+selenium自动化(一)之环境搭建
  4. CV之YOLOv3:基于Tensorflow框架利用YOLOv3算法对热播新剧《庆余年》实现目标检测
  5. linux与shell编程指南,LINUX与UNIX SHELL编程指南
  6. AngularJS HTML DOM
  7. 浅谈格雷码(Grey Code)在信息学竞赛中的应用
  8. jzoj3888-正确答案【字符串hash,dfs】
  9. Java核心(五)深入理解BIO、NIO、AIO
  10. python 返回列表中的偶数
  11. html和css的缺点,个人缺点20个
  12. Linux常用正则表达式
  13. rundeck 内存溢出
  14. 基于SNMP协议的电信网络监测系统的实现
  15. MS17-010漏洞复现(带win7虚拟机安装,零基础)
  16. Python 筛法求素数
  17. 【原型图设计工具】墨刀使用说明
  18. Improved and Efficient Conversational Slot Labeling through Question Answering
  19. 计算机基础文化课认识,【计算机基础论文】计算机基础的教学改革解析(共4653字)...
  20. ai将会怎样影响计算机的发展,AI再升级!人工智能会对我们的未来产生怎样的影响?...

热门文章

  1. 物联网与应用数字战略
  2. Java基础小常识-继承-(10)
  3. HDU 3954 Level up(线段树)
  4. maven 笔记,概念
  5. dll窗体的创建与调用
  6. capistrano
  7. 关于《设计模式》这本书(三)——Proxy模式
  8. C++ 指向常量的指针与指针类型的常量
  9. xpath提取html属性,xpath提取 html标签的文字内容
  10. mitmdump 脚本使用python第三方包方法(报错:in script xxx.py: No module named ‘xxx‘)