numpy arange:如何制作“精确”的花车阵列?

时间:2017-11-11 21:55:42

标签: python arrays numpy

简而言之,我遇到的问题是:

aa = np.arange(-1., 0.001, 0.01)
aa[-1]
Out[16]: 8.8817841970012523e-16

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

我可以这样做:

aa = np.arange(-100, 1, 1)/100.
aa[-1]
Out[21]: 0.0

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

这似乎是一个基本问题。这里有一些我不想要的东西。 顺便说一句,我使用的是Python 2.7.13。

2 个答案:

答案 0 :(得分:3)

这是因为Python(像大多数现代编程语言一样)使用浮点运算,它不能精确地表示某些数字(参见Is floating point math broken?)。

这意味着,无论您使用的是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

类似地:

>>> x = np.arange(-1., 0.001, 0.01)
>>> x[-1]
8.8817841970012523e-16

用于规避这种情况的典型模式是,如果需要重复操作,则尽可能使用整数。所以,举个例子,我会这样做:

>>> x = 0.01 * np.arange(-100, 0.1)
>>> x[-1]
0.0

或者,您可以创建一个单行便捷功能,为您执行此操作:

>>> 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

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

>>> val = -0.99
>>> print('{0:.20f}'.format(val))
-0.98999999999999999112

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

答案 1 :(得分:0)

我们不会忘记浮点算术的局限性。反复添加0.01,或者更确切地说,接近0.01的双精度浮点数将导致您观察到的那种效果。

要确保数组不包含正数,请使用numpy.clip

aa = np.clip(np.arange(-1., 0.001, 0.01), None, 0)