简而言之,我遇到的问题是:
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。
答案 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)