版权声明:此文章转载自 Yushneng PyHub

如需转载请联系听云College团队成员阮小乙,邮箱:ruanqy#tingyun.com

本系列完整文档已托管在 Read the Docs: http://tips.pyhub.cc

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

IEEE 浮点数表示法

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

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

其中 d_i 是十进制中 0~9 的数字。而如果是一个二进制的小数:1.001 = 1 + 0/2 + 0/4 + 1/8

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

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

也就是说用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 + .1b = .3print(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 == c0.1000000000000000055511151231257827021181583404541015625

0.10000000000000010269562977782697998918592929840087890625

0.1000000000000000055511151231257827021181583404541015625

Falsefrom fractions import Fraction

f1 = Fraction(1, 10) # 0.1print(float(f1))

f3 = Fraction(3, 10) # 0.3print(float(f3))

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

0.3

True

总结

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

想技术文章,请访问听云技术博客,访问听云官方网站感受更多应用性能优化魔力。

python理解浮点数运算的误差_PyTips 0x1a - Python 浮点数运算相关推荐

  1. python理解浮点数运算的误差_浅谈浮点数运算的误差

    测试程序 我们知道,浮点数运算存在舍入误差.在某些特殊的情况下,舍入误差还可以累计到非常大的地步.让我们来看一下测试程序吧: 1 usingSystem;2 3 static classDecimal ...

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

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

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

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

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

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

  5. python浮点数怎么运算_Python如何执行精确的浮点数运算

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

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

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

  7. 浮点数运算产生误差的原因详解

    背景:业界主流的IEEE754浮点数标准,对该标准表示浮点数的方法熟知,如诺不知,请参考前篇博文:https://blog.csdn.net/Naruto_c/article/details/8528 ...

  8. python中数据类型不同运算不同_Python的基本数据类型与运算

    Python的基本数据类型: 1.number数字 整型(整数):python可以处理任意大小的整数包括正整数与负整数 浮点型(小数):在Python中表示浮点数的时候回存在一些误差 复数:a+bj ...

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

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

最新文章

  1. 【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | Visual Studio 中 SDK 和 NDK 安装位置 )
  2. 累积计税法:算一算您一年缴了多少个税
  3. Spring MVC不要在@Service bean中保存状态
  4. 很现实、很暴力的面试法则 —— 来自招聘官的自述
  5. JS的Date.setMonth()方法坑
  6. mkv210_image.c文件详解
  7. 太阳能板清洗机器人科沃斯_太阳能电池板清洁机器人
  8. 上传文件的php代码,PHP实现大文件上传源代码
  9. [OpenBMC] 快速上手OpenBMC的Redfish
  10. 报文学习四(LLDP协议)
  11. C++:什么是STL?
  12. vue+el国际化-东抄西鉴组合拳
  13. 处理器哪个好_对比骁龙730G、765G、猎户座980、天玑1000处理器,性能哪个好?
  14. linux权限750什么意思,chmod 777是什么意思?为您解释chmod 777及切勿使用chmod 777的原因...
  15. @Inject和@Named
  16. 研发质量管理工作经验总结(二)----质量管理技能
  17. 妙用CSS变量,让你的CSS变得更心动
  18. 300000000元!短融网获C轮融资,CEO王坤透露了几点信息
  19. 马化腾:搜索、电子商务硬仗一定要坚持打
  20. JAVA基础09——java输入

热门文章

  1. 使用Clang作为库 —— Clang Plugins
  2. VML极道教程(十二) VML编程大结局
  3. 查询选修‘C语言’课程的学生(MSSQL)
  4. 用java生成高并发下的唯一的案件编号:
  5. 如何用ChatGPT搭建品牌文本体系?(品牌名+slogan+品牌故事)
  6. 萌新做点小玩意儿DAY-9 利用队列式分支限界解决抓住那头牛问题
  7. OpenCV保存视频图片相关
  8. Linux下安装Scrapy框架
  9. 0-1背包问题 动态规划c语言,详解动态规划01背包问题--JavaScript实现
  10. happypack打包报错TypeError: this.getOptions is not a function