numpy arange:如何制作“精确”的浮点数组?

Ale*_*lex 8 python arrays numpy

总之,我遇到的问题是这样的:

aa = np.arange(-1., 0.001, 0.01)
aa[-1]
Out[16]: 8.8817841970012523e-16
Run Code Online (Sandbox Code Playgroud)

实际上,这会导致一系列问题,因为我的模拟不允许正值输入。

我可以通过以下方式解决:

aa = np.arange(-100, 1, 1)/100.
aa[-1]
Out[21]: 0.0
Run Code Online (Sandbox Code Playgroud)

但这是一种痛苦。实际上,您不能每次都这样做。

这似乎是一个如此基本的问题。这里一定有我遗漏的东西。顺便说一下,我使用的是 Python 2.7.13。

jak*_*vdp 9

发生这种情况是因为 Python(像大多数现代编程语言一样)使用浮点运算,它不能准确地表示某些数字(请参阅浮点运算是否被破坏?)。

这意味着,无论您使用的是 Python 2、Python 3、R、C、Java 等,您都必须考虑将两个浮点数相加的效果。

np.arange通过重复将step值添加到值来工作start,这最终会导致不精确:

>>> start = -1
>>> for i in range(1000):
...    start += 0.001
>>> start
8.81239525796218e-16
Run Code Online (Sandbox Code Playgroud)

相似地:

>>> x = np.arange(-1., 0.001, 0.01)
>>> x[-1]
8.8817841970012523e-16
Run Code Online (Sandbox Code Playgroud)

用于规避此问题的典型模式是在需要重复操作时尽可能使用整数。所以,例如,我会做这样的事情:

>>> x = 0.01 * np.arange(-100, 0.1)
>>> x[-1]
0.0
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个单行便利函数来为您执行此操作:

>>> def safe_arange(start, stop, step):
...    return step * np.arange(start / step, stop / step)

>>> x = safe_arange(-1, 0.001, 0.01)
>>> x[-1]
0
Run Code Online (Sandbox Code Playgroud)

但请注意,即使这样也无法绕过浮点精度的限制;例如,数字 -0.99不能用浮点精确表示

>>> val = -0.99
>>> print('{0:.20f}'.format(val))
-0.98999999999999999112
Run Code Online (Sandbox Code Playgroud)

因此,在使用任何语言处理浮点数时,您必须始终牢记这一点。