使用 IPython 时避免小的数值错误

Avoiding small numerical errors when using IPython

我一直在从 Matlab 切换到 IPython。 在IPython中,如果我们将3.1乘以2.1,结果如下:

In [297]:

3.1 * 2.1
Out[297]:
6.510000000000001

存在小的舍入误差。这不是什么大问题,但有点烦人。我假设它是在将十进制数转换为二进制数时出现的,反之亦然,对吗?

然而,在 Numpy 数组中,结果是正确的:

>>> np.array([3.1 * 2.1])
array([ 6.51])

在Matlab命令行提示下,结果也是正确的:

>> 3.1 * 2.1

ans =

    6.5100

Python 中的上述舍入错误看起来很烦人。在 python 交互模式或 IPython 中是否有一些方法可以避免此错误?

numpy 结果并不比纯 Python 更精确 - 浮点不精确只是对您隐藏,因为默认情况下,numpy 打印结果的小数位数较少:

In [1]: float(np.array([3.1 * 2.1]))
Out[1]: 6.510000000000001

您可以使用 np.set_printoptions 控制 numpy 显示浮点数的方式。例如,要打印 16 位小数而不是通常的 8 位:

In [2]: np.set_printoptions(precision=16)

In [3]: np.array([3.1 * 2.1])
Out[3]: array([ 6.5100000000000007])

在 IPython 中,您还可以使用 %precision 魔法来控制漂亮打印正常 Python 浮动时显示的小数位数:

In [4]: %precision 8
Out[4]: u'%.8f'

In [5]: 3.1 * 2.1
Out[5]: 6.51000000

请注意,这纯粹是装饰性的 - 3.1 * 2.1 的值仍将等于 6.5100000000000006750155990... 而不是 6.51

在 Octave 中,一个 MATLAB 克隆,我可以显示那些遥远的小数:

octave:12> printf("%24.20f\n", 3.1*2.1)
     6.51000000000000067502

他们也出现在你的numpy.array

In [6]: np.array([3.1*2.1]).item()
Out[6]: 6.510000000000001

即使是组成项也涉及这种舍入:

octave:13> printf("%24.20f\n", 3.1)
  3.10000000000000008882
octave:14> printf("%24.20f\n", 2.1)
  2.10000000000000008882