0、1 + 0.68 不等于 1.68

我们先来看一行简单的代码:

a = 1 + 0.68

b = 1.68

is_equal = (a == b)

print("{}=={}is{}".format(a, b, is_equal))

逻辑上,上面的代码的输出结果应该为:

1.68 == 1.68 is True

然而,实际上真正的输出结果是:

1.6800000000000002 == 1.68 is False

你是否在实际的开发过程中遇到类似的问题,并因为付出了大量的DEBUG时间,最终才发现这么一个违反直觉的现象。

我们可以信手就举几个违反直觉的、看似相等,实则不想等的例子:

0.1 + 0.1 + 0.1 == 0.3 # False

0.99 * 3 == 2.97 # False

事实上,这个问题是所有编程语言都会遇到的问题,它都不能算是一个BUG,而算是一个非常正常的现象。

那么问题来了:我们怎么才能比较两个浮点数是否想等呢?

我们将在本文的最后回答这个问题。

1、浮点数的精度问题

我们都知道,计算机是以二进制的形式保存数据的。无论是整数还是浮点数,都不例外。举个例子,十进制浮点数字0.125的二进制表达式为:

0.001

# 0.125 = 0*2 + 0/2 + 0/4 + 1/8

# 0. 0 0 1

如果你看不懂上面的转换,你应该先了解一下十进制浮点数与二进制浮点数之间的转换,再来阅读本文。本文是在假设你已经了解这个规则的基础上编写的。

我们知道,当我们用十进制小数表达1/3的时候,它是一个无穷循环的小数。

# 1/3 的十进制小数表达:

0.33333333333333333333333333...

我们无法穷举所有的3,所以没有办法通过穷举再准确地表达1/3,而只是通过尽量多的穷举,去更接近的表达(近似表达)。

同样的,计算在表达一个数值(二进制)的时候,也是通过只能通过穷举一定的位数,来达到表达一个浮点数的效果。当计算机表述一个64位的浮点数时,一般是用10位来表达指数,用54位来表达精度。所以,当一个小数的位数超过54的时候,计算机就无法精准的表达,而只能取其近似值。

举个例子,十进制数0.1的二进制表达式为:

0.0001100110011001100110011001100110011001100110011...

如果是64位的浮点数,那么计算机只能取小数点后54位的精度。

我们先来看一段代码:

a = 0.1

print(a)

print("{:.20f}".format(a))

其它结果为:

0.1

0.10000000000000000555

第一个打印的结果,看似正确,事实上只是一个表象;这是计算机为我们做了尽量接近原数值的推算和展示(这个超过本文的讨论范围,不深入讨论)。

当我们把精度取到20位的时候(第二行结果),我们就会出现计算机在存储0.1的这数值的时候,其实并不是准确的存储了0.1,而是存储了一个近似值。正如我们前面所提到的,用有限位的二进值小数,并没有办法精确的表达十进制小数0.1。

2、如何比较两个浮点数是否相等

很遗憾,我们的答案是:不能。

这是一个非常重要的计算机常识。

如果你尝试通过==来判定两个浮点数是否相等,你有可能就陷入了第一节所讨论的陷阱。所以,除非你非常明确自己的意图,否则你千万不要这么做。

但是判定两个浮点数是否相等,却是一个非常普通而常见的操作,我们应该怎么做呢?

答案是:取近似值。

当我们直接用==判定两个64位浮点数(注意我们这里提到了位数)是否相等时,事实上是对比两个浮点数在54位的精度上(与小数点后54不是同一个概念)的近似值是否相等。

同理,当你判定两个浮点数是否相等时,你应该取一个适当的精度。而这个精度应该根据你实际功能的需要决定。

回到我们第0节所提到的1.68的问题,当我们取小数点后15位以内时,这两个数值就可以判定为近似相等。

a = 1.68

b = 1 + 0.68

print("a={:.20}".format(a))

print("b={:.20}".format(b))

eps = 0.00001

if abs(a - b) < eps:

print("a == b")

上面代码的打印结果为:

a=1.6799999999999999378

b=1.6800000000000001599

a == b

浮点数计算一个很专业和复杂的问题,我这里只是抛砖引玉,简单地介绍,如果你感兴趣,可以专门去了解一下。这里有几个链接仅各位参考一下:https://docs.python.org/3/tutorial/floatingpoint.html​docs.python.orgBinary numbers – floating point conversion​blog.penjee.com

python布尔运算可以比较浮点数吗_Python3 基础之:令人困惑的浮点数运算相关推荐

  1. python取的键不存在_Python3基础 dict get 在查询不存在的键时,返回指定的内容

    Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda : 4.5.11 typesetting : Markdown ...

  2. python读取txt文件每一行_Python3基础 file for+list 读取txt文本 并 一行一行的输出(低效率)...

    Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda : 4.5.11 typesetting : Markdown ...

  3. python 写文件 不存在创建_Python3基础 文件write 与 open(w) 对一个不存在的txt进行创建与写入...

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体. ------------------------------------- ...

  4. python中not加变量是_Python3基础 in 与 not in 判断一个变量是否在列表中存在

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体. ------------------------------------- ...

  5. python类的定义和使用_Python3基础之python 之 面向对象基础(定义类、创|python基础教程|python入门|python教程...

    第七章面向对象 1.面向过程编程核心是"过程"二字,过程指的是解决问题的步骤,即先干什么再干什么基于该思想编写程序就好比在编写一条流水线,是一种机械式的思维方式 优点:复杂的问题流 ...

  6. 如何找到python廖雪峰基础_python3 基础 廖雪峰教程笔记-1

    廖雪峰教程文档:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143252 ...

  7. python怎么输出浮点数_python 零基础入门教程第 2 章:基本数据类型 (一)

    一.什么是数据类型 编程语言通过一些复杂的计算机物理底层机制,创造不同类型的数据,用来表示现实世界中的不同信息,以便于计算机更好的存储和计算. 每种编程语言都会有一些基本的数据类型用来表示现实世界中的 ...

  8. python编程中常用的12种基础知识总结

    python编程中常用的12种基础知识总结:正则表达式替换,遍历目录方法,列表按列排序.去重,字典排序,字典.列表.字符串互转,时间对象操作,命令行参数解析(getopt),print 格式化输出,进 ...

  9. Python 数据分析与展示笔记1 -- Numpy 基础

    Python 数据分析与展示笔记1 – NumPy 基础 Python 数据分析与展示系列笔记是笔者学习.实践Python 数据分析与展示的相关笔记 课程链接: Python 数据分析与展示 参考文档 ...

最新文章

  1. java异常处理试题答案_JAVA异常处理试题及答案
  2. MATLAB优化问题
  3. 数据结构与算法之“之”字型打印矩阵和矩阵中找数
  4. me shy是什么歌 抖音make_内含活动福利 | 小红书、抖音爆赞的高颜值的北欧家居神店开到卜蜂中心啦!...
  5. github gists 101使代码共享漂亮
  6. 乘法原理的例题和答案_吃透高考数学17个必考题型,基础再差也能考130!(内附解题技巧+例题解析)...
  7. [算法 笔记]2014年去哪儿网 开发笔试(续)第一题BUG修正
  8. 华为云整合三朵云能力,第二阶段决战大政企战场
  9. 蔡高厅老师 - 高等数学阅读笔记 - 02 - 极限(06 、07、08、09、10、11、12)
  10. ArrayList和LinkedList的插入删除性能差距到底有多大
  11. SQL http://www.myfeng.cn/?T3009
  12. 如何深入浅出地讲解麦克斯韦方程组
  13. java 链表插入排序,insertion Sort List (链表的插入排序) leecode java
  14. ios平台实现视频H264硬编码及软编码(附完整demo)
  15. 拍拍抢拍精灵v2.1秒杀器所有源代码【开源】
  16. js 精确判断对象的类型
  17. Android 开源项目分类汇总(很全)
  18. 一种高性能无锁队列设计
  19. 计算机开机桌面空白,电脑开机桌面一片空白是怎么回事?
  20. html5 2019新年祝福页面,2019新年创意祝福语 绝对让你的心意顺利送达

热门文章

  1. 超火网络直播短视频宣传海报PSD分层模板,新媒体互动
  2. 设计师必备的设计导航站,工作简单化
  3. UI干货素材模板|从做好网页头部内容设计开始!
  4. python 条形图 负值_Python处理JSON数据并生成条形图
  5. postman中文设置_严选 | Elastic中文社区201902错题本
  6. c++ 14新的语法特性之返回类型推导
  7. 【数学建模】通过调整飞行角度使飞机顺利飞行(Matlab)
  8. X86 register
  9. Decision Tree(DT)决策树
  10. 【linux指令】dialog实现终端下的GUI-1