提问人:AFoeee 提问时间:10/27/2018 最后编辑:Paul RoubAFoeee 更新时间:9/21/2019 访问量:1504
为什么 math.isclose() 无法检测到非常大的值之间的微小差异?
Why does math.isclose() fail to detect minor differences between very large values?
问:
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”的答案。
答:
6赞
Tim Peters
10/27/2018
#1
sys.maxsize
是一个整数,但适用于浮点值。在 64 位盒子上,精度比浮点数可以表示的要多,因此对于所有足够小的正整数。math.isclose()
sys.maxsize
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
短期课程:当您想比较整数是否相等时,首先转换为浮点数根本没有意义。
评论
0赞
AFoeee
10/27/2018
我很困惑。 指定 1.7976931348623157e+308 作为最大值。如果它的射程小于?sys.float_info.max
sys.maxsize
1赞
Tim Peters
10/27/2018
sys.float_info.max
是浮点数可以具有的最大值。Python 整数的最大值没有固有限制。 只是用作索引的 Python 整数可以具有的最大值。这是三个不同的概念。sys.maxsize
1赞
Tim Peters
10/27/2018
顺便说一句,如果您需要了解浮点的基础知识,只需搜索网络即可。例如,en.wikipedia.org/wiki/Floating-point_arithmetic 在浮点数中,精度位数与最大动态范围(指数可以有多大)之间没有特定的联系。在您的机器上,Python 浮点数几乎可以肯定具有(确切地)53 位精度,但动态范围跨越大约 600(十进制)数量级(标准 IEEE-754“双精度”格式的所有特征)。
0赞
AFoeee
10/28/2018
如果我理解正确,则发生上述行为是因为我使用整数值而不是浮点值。使用非常大的浮点值时,似乎也会发生类似的事情。(我在问题中添加了一个示例。我想这也是因为超出了精度限制。有没有可以安全操作的范围?
评论