前言
对于这篇文章中记录的内容,不确定是否正确,毕竟这玩意儿不好验证。(比如文中提到“计算机打印机制会骗人”这一点)
查阅了一些资料以及 ChatGPT,得到的回复是这样的。所以就做了个简短的记录。
其实对于本篇提及的问题,我主要关注两点:
- 认识到问题的存在(能理解具体原因最好)
- 知道如何解决可能遇到的问题 👉🏻 如何判断两个浮点数的相等?
问题描述
在学习很多编程语言时,提到浮点数,不少老师总是会提一嘴浮点数计算失真的问题。
但是蛮多老师都是非常快速地一嘴带过了。
意识到这个问题其实是一个普遍的问题,并不限于某种特定的编程语言,比如在 JavaScript、Python…… 中都存在,于是想要写一写自己对此的理解,下次学习其它编程语言遇到老师介绍这个问题时,直接跳过便是。
为什么有些浮点数计算失真有些不失真?
一句话总结:进制转换导致精度丢失,及计算机打印机制的欺骗
- 计算机存储数据采用的是二进制的形式,所以我们传递的十进制小数最终都要转为二进制形式进行计算
- 某些小数无法通过二进制精确的表示,计算机在使用二进制来表示这些小数时,会使用有限的空间来表示它们
- 给的空间越多,自然就越是接近,但最终只能无限接近,永远不会相等
- 就好比我们没法用小数来表示
1/3
一样,我们会使用0.333333333333333333……
这么一个无限循环小数来表示1/3
- 计算机在计算完之后,我们获取到计算机计算后的结果,然后将其打印出来,这时候需要将二进制再转换为十进制,这又涉及到计算机的打印机制。对于一些计算结果
0.1 + 0.3
也许它们也是失真的,可是打印出来却是0.4
符合我们预期的。这其实是计算机的打印机制让我们误以为结果是正常的,其实0.1 + 0.3
的结果也可能有精度的损失,只是这个损失在二进制和十进制之间的转换中被四舍五入掉了
大部分都是会失真的,只不过有时候我们打印出来看到的结果,看似是没有失真罢了。
如何判断两个浮点数的相等?
不推荐直接比较两个浮点数是否相等,而是比较它们的差的绝对值是否小于一个非常小的数,这样可以避免因为浮点数精度问题导致的错误结果
# 不推荐的做法
0.1 + 0.2 == 0.3 # False
# 推荐的做法
(0.1 + 0.2) - 0.3 < 0.000000001 # True
遇到高精度的需求咋办?
不知道……
就日常业务中,还真没接触过类似的需求……
不同的语言找不同的工具来解决叭!
对于需要高精度小数计算的应用,通常需要采用特殊的数据结构和算法,例如使用定点数表示法,或者使用任意精度的数学库,如 Python 的 decimal 模块等。