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

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! "**"运算这个"**"比较简单,就是标 ...

  2. python中的乘方_python乘方运算

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 算数运算符是完成基本的算术运算使用的符号,用来处理四则运算运算符描述实例+加10 ...

  3. python复数的概念及运算_python 复数运算

    复数的数学运算 复数可以用使用函数 complex(real, imag) 或者是带有后缀j的浮点数来指定.比如: >>> a = complex(2, 4) >>> ...

  4. python浮点数怎么表示_python浮点数

    浮点数是近似值,它们不能精确地存储十进制数.因为它们试图仅以64位表示非常大的数字范围,所以它们必须在某种程度上接近. 了解这一点非常重要,因为它会导致一些奇怪的副作用.例如,您可能会非常合理地认为十 ...

  5. python与或非位运算_python位运算

    什么是位运算 位运算就是把数字当成二进制来进行计算,位运算有六种:&(与), |(或), ^(异或), ~(非), <>(右移) &(与) &运算规则:两个位都为1 ...

  6. python浮点数多少位_python 浮点数保留几位小数

    原博文 2019-11-27 10:41 − In [1]: a = 5.026 In [2]: b = 5.000 In [3]: round(a,2) Out[3]: 5.03 In [4]: r ...

  7. python中集合运算_python集合运算

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 每个韦恩(venn)图中的红色部分是给定集合运算得到的结果.? python 集 ...

  8. python拟合三元函数_Python三元运算和Python函数介绍

    三元运算:if 1+1 == 2 : print (True) else: print (False) #等同于: print (True if 1+1==2 else False) 函数的基本语法d ...

  9. python语言arrows用法_python时区运算,时区,时间戳,夏令时讲解

    import arrow from datetime import datetime import pytz def test_demo(): """ arrow 实例 ...

最新文章

  1. 7 Papers Radios | Transformer自动debug;AI合成舞蹈落地应用
  2. 去月球“挖土”咯!今天发射的嫦娥五号实现四个“首次”,下个月将样品带回地球...
  3. 【Python-ML】SKlearn库多项式回归
  4. Qt使用UDp通信、套接字socket的成员函数bind()的作用
  5. linux环境搭建golang服务器,Linux下golang环境搭建-Go语言中文社区
  6. c++代码转为go_Go调用C/C++
  7. acwing2019. 拖拉机(最短路径)
  8. java项目添加jar包
  9. JAVA设计模式之【外观模式】
  10. 天池csv转成grt代码里的luna的csv,pandas库来操作csv文件(pd.DataFrame,pd.concat,pd.Series,to_csv等)实现
  11. 10 -3 2用c语言怎么打,(3*20+30-10)/2怎么使用C语言编写
  12. 哪些Mac快捷键可以精准定位光标位置
  13. arcgis取反+掩膜提取
  14. 孙鑫VC学习笔记:第十二讲 (五) 往win.ini的文件中写入数据
  15. 飞思卡尔单片机高效c语言编程,飞思卡尔单片机高效c语言编程(中文)新.pdf
  16. Altium 怎么设置鼠标滚轮放大缩小
  17. 当天使爱上吸血鬼,上帝开始哭泣
  18. 变量消元(Varible Elimination)和概率边缘化(Marginalization)的关系
  19. Kali安装VirtualBox增强功能
  20. TCL发布两款可穿戴设备;中兴通讯推出第三代5G室内路由器;绘王联合制作《河岸》获棕榈泉国际短片电影节最佳动画奖 | 全球TMT...

热门文章

  1. 2019 最烂密码榜单出炉,教你设置神级密码!
  2. Android列表用法之二:实战ListView高级用法
  3. 经验分享 | 微信公众账号怎么搭建微信社区?
  4. 什么是mysql的读写分离_什么是数据库读写分离?
  5. 大学生求职心切谨防陷阱 试用期不是白用期
  6. IDEA如何修改快捷键
  7. http://ec.iresearch.cn/reservation/20150327/248051.shtml#6634817-qzone-1-22915-3e7edfcacfa3df75b7a4b
  8. 【ORB-SLAM3论文翻译】ORB-SLAM3:一个精确的视觉、视觉惯性和多地图SLAM的开源库(注:带着原文看,很多公式和变量不好输入)
  9. linux 终端打开gedit,gedit命令运行时我无法使用终端
  10. js给input赋值无效的问题