使用math.isclose函数,其值接近0

ste*_*fen 11 python math floating-point precision python-3.x

我们知道,由于数字的二进制表示,此表达式的计算结果为False(至少在Python中):

0.2 + 0.4 == 0.6
Run Code Online (Sandbox Code Playgroud)

为了能够检查数字错误中的相等性,该模块math提供isclose:

import math
math.isclose(0.2 + 0.4 , 0.6)
Run Code Online (Sandbox Code Playgroud)

最后一个表达式True按预期产生.

现在为什么这个表达式False再次出现?

math.isclose(0.2 + 0.4 - 0.6 , 0.0)
Run Code Online (Sandbox Code Playgroud)

看来,一切相比,0.0False

math.isclose(1.0e-100 , 0.0)
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 17

答案可以通过阅读文档来解决.

math.isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0)
Run Code Online (Sandbox Code Playgroud)

如果值a和b彼此接近则返回True,否则返回False.

根据给定的绝对和相对容差确定两个值是否被认为是接近的.

rel_tol是相对容差 - 它是a和b之间允许的最大差值,相对于a或b的较大绝对值.例如,要设置5%的容差,请传递rel_tol = 0.05.默认容差为1e-09,可确保两个值在大约9个十进制数字内相同.rel_tol必须大于零.

abs_tol是最小绝对容差 - 对于接近零的比较很有用.abs_tol必须至少为零.

如果没有错误发生,结果将是:

abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
Run Code Online (Sandbox Code Playgroud)

您使用默认容差,这意味着使用相对容差检查.上面的等式清楚地表明了为什么你的表达式评估为false.

考虑问题中的最终表达:

math.isclose(1.0e-100 , 0.0)
Run Code Online (Sandbox Code Playgroud)

将这些值插入文档中的表达式,我们有

1.0e-100 <= max(1.0e-9 * 1.0e-100, 0.0)
Run Code Online (Sandbox Code Playgroud)

我认为显而易见的是,在执行相对容差比较时,使用默认容差,不会将非零值视为接近零.

对于非常小的值,您应该使用绝对容差.

或者您应该重新编写测试以避免与零进行比较.

  • 为了完整起见,[原始PEP](https://www.python.org/dev/peps/pep-0485/#absolute-tolerance-default)解释了为什么绝对公差为0:*"确定所需的绝对公差如果值"接近"为零则完全依赖于用例."* (3认同)
  • mmph。我确实阅读了文档,并指出可以设置相对公差和绝对公差。但是我以某种方式错过了默认的绝对公差为0.0。也许我应该去睡觉...谢谢大卫 (2认同)