【问题标题】:numpy arange: how to make "precise" array of floats?numpy arange:如何制作“精确”的浮点数组?
【发布时间】:2017-11-11 21:55:42
【问题描述】:

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

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。

【问题讨论】:

  • linspace 有帮助,但不能解决所有问题。
  • 是的,我有时会使用 linspace。但你知道有时 arange 更方便:)
  • 尝试使用linspace。浮点数本质上具有一些噪声,并且 arange (精确地)不适用于非整数增量。或者,如果必须,手动将最后一个元素设置为 0.0。
  • 他们在 python 3 中修复了这个问题吗?
  • 用有限位表示实数的基本限制无法通过版本升级来解决。

标签: python arrays numpy


【解决方案1】:

发生这种情况是因为 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

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

【讨论】:

    【解决方案2】:

    使用 np.linespace 为我解决了这个问题:

    例如np.linspace(0.5, 0.9, 5) 产生 [0.5 0.6 0.7 0.8 0.9]。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 谢谢。 np.clip 适用于这个特定问题。但是数组中的所有其他元素仍然略有偏差。不幸的是,当时的情况似乎就是这样。
      • 是的,就是这样。 0.1+0.2 == 0.3 是False,我们必须忍受它(在 Python 3 和其他语言中也是如此)。见Is floating point math broken?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多