python - 为什么 math.isclose() 无法检测到非常大的值之间的微小差异?

标签 python python-3.x compare precision equality

math.isclose() 的存在是为了确定两个值之间的差异是否在容差范围内。
据我了解,此公差的默认值为:

  • rel_tol = 1e-09
  • abs_tol = 0.0


如果我将两个值都设置为 0.0,那么它应该测试这两个值是否相同。

这似乎适用于较小的值:

import math

math.isclose(1000, 1000, rel_tol=0.0, abs_tol=0.0)                       # True
math.isclose(1000, 1001, rel_tol=0.0, abs_tol=0.0)                       # False

但它失败了非常大的值:

import math
import sys

math.isclose(sys.maxsize, sys.maxsize,      rel_tol=0.0, abs_tol=0.0)    # True
math.isclose(sys.maxsize, sys.maxsize-1,    rel_tol=0.0, abs_tol=0.0)    # True
math.isclose(sys.maxsize, sys.maxsize-100,  rel_tol=0.0, abs_tol=0.0)    # True
math.isclose(sys.maxsize, sys.maxsize-1000, rel_tol=0.0, abs_tol=0.0)    # False

好像还有相对容忍度?


为什么会出现这种行为?

以上代码使用 Python 3.5.2 运行。


更新 1:

似乎在使用非常大的浮点值时会发生类似的行为:

import math
import sys

m = sys.float_info.max                                                    # type 'float'

math.isclose(m, m)                                                        # True
math.isclose(m, m-1.0)                                                    # True
math.isclose(m, m-1e100)                                                  # True
math.isclose(m, m-1e300)                                                  # False

math.isclose(m, m,       rel_tol=0.0, abs_tol=0.0)                        # True
math.isclose(m, m-1.0,   rel_tol=0.0, abs_tol=0.0)                        # True
math.isclose(m, m-1e100, rel_tol=0.0, abs_tol=0.0)                        # True
math.isclose(m, m-1e300, rel_tol=0.0, abs_tol=0.0)                        # False

另一方面,比较运算符在这里也不起作用。

import math
import sys

m = sys.float_info.max                                                    # type 'float'

m == m                                                                    # True
m < m                                                                     # False
m > m                                                                     # False

m == m-1.0                                                                # True
m < m-1.0                                                                 # False
m > m-1.0                                                                 # False

m == m-1e100                                                              # True
m < m-1e100                                                               # False
m > m-1e100                                                               # False

m == m-1e300                                                              # False
m > m-1e300                                                               # True
m < m-1e300                                                               # False

更新 2:

“更新 1”的答案已给出 here .

最佳答案

sys.maxsize 是一个整数,但 math.isclose() 适用于浮点值。在 64 位机器上,sys.maxsize 比 float 可以表示的精度更高,所以 float(sys.maxsize - N) == float(sys.maxsize) 对于所有足够小的正整数 N

>>> from sys import maxsize as m
>>> m
9223372036854775807
>>> float(m)
9.223372036854776e+18
>>> float(m - 1)  # identical
9.223372036854776e+18
>>> float(m - 100) # identical 
9.223372036854776e+18
>>> float(m - 1000)  # finally subtracting enough to make a tiny difference
9.223372036854775e+18

简短类(class):当您想比较整数是否相等时,首先转换为 float 根本没有意义。

关于python - 为什么 math.isclose() 无法检测到非常大的值之间的微小差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53017563/

相关文章:

python - 我正在寻找根据用户输入创建类的实例

python - 如何通过索引一次将多个值插入到列表中

python - 处理 argparse 输入中的空格

python - 为什么这个算法对于不是 2 的幂的整数会失败?

python - 为什么我会收到此错误 : "could not convert string to float: ' .' "? 为什么它不适用于大于 10 的数字?

c++ - 自定义排序和映射时更喜欢函数指针还是函数对象?

python - Pandas 过滤或删除行多个条件

python - Pandas 如何获取连续日期和销售额超过 1000 的行?

java - 如何使 compareTo 方法尊重一般契约(Contract)?

.net - 用于以编程方式比较程序集 .NET(反射、MSIL)的 API