浮点数用来存储计算机中的小数,与现实世界中的十进制小数不同的是,浮点数通过二进制的形式来表示一个小数。在深入了解浮点数的实现之前,先来看几个 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 中使用更精确的浮点数可以通过 decimal 和 fractions 两个模块,从名字上也能猜到,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 科学计算包。

python理解浮点数运算的误差_Python 浮点数运算相关推荐

  1. python理解浮点数运算的误差_浮点数运算的机器误差分析

    感觉跟专栏主题不是很搭... 不过这是这学期计算物理的作业,还是放上来吧,也算勉强沾边了吧. 用一个浮点数相加的例子来演示计算机在计算时所产生的误差. 在Python中,用0.2+0.4 会得到0.6 ...

  2. 在python中浮点数怎样转整数_python 浮点数 转 整数python函数每日一讲 - all()

    W WW.002pc .COM对<python 浮点数 转 整数python函数每日一讲 - all()>总结来说,为我们python培训很实用. all(iterable) 版本:该函数 ...

  3. python 浮点数精度不准确_python 浮点数不精确原因

    今天遇到有人问我哥问题, a = 7.1sum= a / 1000 print(sum) 输出:0.0070999999999999995 问:不应该是0.0071吗?怎么多了那么多小数位?我虽然知道 ...

  4. python支持的集合运算有哪些_Python集合运算

    在对集合做运算时,不会影响原来的集合,而是返回一个运算结果 创建两个集合 s = {1,2,3,4,5} s2 = {3,4,5,6,7} & 交集运算 result = s & s2 ...

  5. 07 理解浮点数运算的误差

    # 理解浮点数运算的误差def cni(n,i):minNI = min(i, n-i)result = 1for j in range(0, minNI):result = result * (n ...

  6. java浮点数误差_浮点数运算的误差

    浮点数运算的误差 在 JavaScript 中整数和浮点数都属于number 数据类型,所有数字都是使用64位浮点数形式储存,遵循IEEE-754双精度标准存储,即便整数也是如此. 所以我们在打印 1 ...

  7. python浮点数怎么运算_为什么说浮点数缺乏精确性? python中浮点数运算问题

    我想从两个角度回答: 一:十进制小数转化成二进制小数的方法.(简单举例,看完就可以自己用笔进行运算.) 二:如何解决python中的浮点数运算问题. 关于一: 拿1.375这个十进制数举例,pytho ...

  8. [转载] python怎么将十进制转换为二进制_python十进制和二进制的转换方法(含浮点数)

    参考链接: Python中的十进制函数 1 本文介绍了python十进制和二进制的转换方法(含浮点数),分享给大家,也给自己留个笔记,具体如下: 我终于写完了 , 十进制转二进制的小数部分卡了我将近一 ...

  9. python中不同类型的数据不能相互运算_Python第三课——数据类型与运算(2)

    hello大家好,我是你们的小蒟蒻鸭,终于终于有时间写博客了(虽然刚开始期末复习),真的非常非常抱歉,拖更太厉害了.反正还有一个月不到小蒟蒻就要放暑假了!!!(激动.jpg),蒟蒻保证会一周两篇,绝不 ...

最新文章

  1. 致广州达到信息技术有限公司
  2. Android教程 -09 数据的持久化存储
  3. 因新漏洞问题 Firefox 49发布时间将延期一周
  4. 字典树模板+洛谷P2580 于是他错误的点名开始了
  5. CVPR 2022 | 天大本科生论文入选!深度学习长尾分类新SOTA
  6. bootstraptable中responsehandle获取数据缺失_Python中的向量化字符串操作
  7. java list 有向图_Java检测循环有向图
  8. 最近很火的桌面小猫代打器 人性化UI设置界面
  9. Nikitosh 和异或 —— 一道 trie 树的题用可持久化 trie 水 然后翻车了...
  10. 设置log缓存_全局变量、事件绑定、缓存爆炸?Node.js内存泄漏问题分析
  11. Linux Shell编程参考大全
  12. python epub转txt_怎么将很多个TXT合并成epub?
  13. NVIDIA-CUDA编程初探
  14. 含泪整理最优质Fbx 3d模型素材,你想要的这里都有
  15. 如何对研发团队绩效进行考核--附各环节人员考核参考表
  16. 【100%通过率】华为OD机试真题 Java 实现【预订酒店】【2022.11 Q4 新题】
  17. HTTP网页从请求到响应过程详解
  18. 【Flutter脱发实录】盘一盘InheritedWidget
  19. 关于高可用的系统【转自酷壳】
  20. 一个点击日历框取得时间的例子

热门文章

  1. pgadmin转mysql_postgreSQL使用pgAdmin备份服务器数据的方法
  2. 音乐播放界面(Music playing interface)
  3. 教程向|如何更好还原褶皱,ZBrush雕刻褶皱的技巧
  4. Jsp入门1Jsp入门基础简介与工作原理详解
  5. 使用Nexus Repository 3的十二个理由
  6. Sublime+Xelatex+latextools配置参考文献的诸多问题
  7. 视错觉结合UI:从一个看似简单的自定义控件说起
  8. 太有才了!创新的街头涂鸦手绘欣赏【中篇】
  9. 实例讲解用.NET技术将Excel表格中的数据导入到特定的SQL Server数据库中
  10. 不能再担任法定代表人的情形是哪些