在 Python 中比较数字的一般方法

General way of comparing numerics in Python

我一直在四处寻找比较 Python 中两个数字的通用方法。特别想弄清楚它们到底是不是一样的

Python中的数值类型为:

int, long, float & complex

例如,我可以通过简单地说来比较 2 个整数(一种数字):

a == b

对于浮点数,由于舍入精度,我们必须更加小心,但我可以在一定的公差范围内比较它们。

问题

我们得到 2 个通用数值 ab:我们如何比较它们?我正在考虑将两者都转换为复数(如果类型是 int,那么虚部将是 0)并在该域中进行比较?

这个问题比直接比较浮点数更笼统。肯定和这个问题有关,但又不一样。

为什么不直接使用 ==

>>1 == (1+0j)
True
>>1.0 == 1
True

我很确定这适用于所有数字类型。

如果您要比较不同类型的数字,== 运算符没有任何问题:Python 将处理类型转换。考虑以下因素:

>>> 1 == 1 + 0j == 1.0
True

在您进行可能导致精度损失的数学运算(尤其是浮点数)的情况下,一种常见的技术是检查值是否在一定的公差范围内。例如:

>>> (10**.5)**2
10.000000000000002
>>> (10**.5)**2 == 10
False

在这种情况下,您可以找到差异的绝对值并确保它在某个阈值以下:

>>> abs((10**.5)**2 - 10) < 1e-10
True

在 Python 3.5(和 Numpy)中你可以使用 isclose

阅读 PEP 485 that describes it, Python 3.5 math library listing and numpy.isclose 了解更多信息。 numpy 版本适用于支持 numpy 的所有 Python 版本。

示例:

>>> from math import isclose
>>> isclose(1,1.00000000001)
True
>>> isclose(1,1.00001)
False

可以更改相对和绝对公差。

相对公差可以认为是两个值之间的 +- 百分比:

>>> isclose(100,98.9, rel_tol=0.02)
True
>>> isclose(100,97.1, rel_tol=0.02)
False

绝对公差是两个值之间的绝对值。和abs(a-b)<=tolerance

的测试一样

Python 的所有数值类型都支持 Python 3.5 版本。 (使用复杂的 cmath 版本)

我认为从长远来看,这是您对数字的更好选择。对于较旧的 Python,只需导入源代码。 Github 上有一个版本。

或者,(放弃错误检查和 infNaN 支持)你可以只使用:

def myisclose(a, b, *, rel_tol=1e-09, abs_tol=0.0):
   return abs(a-b) <= max( rel_tol * max(abs(a), abs(b)), abs_tol )