来自 NumPy 的极低值
Extremely low values from NumPy
我正在尝试在 Numpy 中执行一些不同的操作(mean
和 interp
),并且通过这两种操作我在不同的时间得到结果 2.77555756156e-17
,通常是我期待一个零。 即使尝试使用 array[array < 0.0] = 0.0
过滤掉这些值也无法删除这些值。
我假设是某种基础数据类型或环境错误导致了这种情况。数据应该都是浮点数。
编辑:有人指出,我只是过滤掉了 -2.77555756156e-17 的值,但仍然看到正数 2.77555756156e-17。问题的症结在于 什么可能导致这些古怪的值 在执行简单函数时出现,例如在 0-10 之间插值并取同一范围内的浮点数的平均值,以及如何才能我避免了它,而不必在每个语句后显式过滤数组。
您可以将您的值四舍五入为 15 位数字:
a = a.round(15)
现在数组 a
应该显示 0.0
个值。
示例:
>>> a = np.array([2.77555756156e-17])
>>> a.round(15)
array([ 0.])
这很可能是浮点运算错误的结果。例如:
In [3]: 0.1 + 0.2 - 0.3
Out[3]: 5.551115123125783e-17
不是您所期望的那样? Numpy 有一个内置的 isclose()
方法可以处理这些事情。此外,您可以使用
查看机器精度
eps = np.finfo(np.float).eps
所以,也许这样的事情也能奏效:
a = np.array([[-1e-17, 1.0], [1e-16, 1.0]])
a[np.abs(a) <= eps] = 0.0
您运行正在研究数值精度,这是数值计算中的一个重要话题;当您使用浮点数进行任何计算时,您 运行 冒着 运行 变成微小值的风险,例如您在此处发布的值。发生的情况是您的计算产生的值无法完全用浮点数表示。
浮点数用固定数量的信息表示(在Python中,这个数量默认为64位)。您可以在非常好的 Floating point Wikipedia page 上阅读有关如何对信息进行编码的更多信息。简而言之,您在计算平均值的过程中执行的一些计算会产生无法精确表达的中间值。
这不是 numpy 的 属性(它甚至不是 Python 的 属性);它实际上是计算机本身的 属性。你可以在 repl 中查看这是正常的 Python:
>>> repr(3.0)
'3.0'
>>> repr(3.0 + 1e-10)
'3.0000000001'
>>> repr(3.0 + 1e-18)
'3.0'
对于最后的结果,您会期望 3.000000000000000001
,但该数字无法用 64 位浮点数表示,因此计算机使用最接近的近似值,在这种情况下只是3.0
。如果您尝试计算以下数字列表的平均值:
[3., -3., 1e-18]
根据您对它们求和的顺序,您可能会得到 1e-18 / 3.
,即 "correct" 答案,或者为零。你的处境有点陌生;您希望抵消的两个数字并没有完全抵消。
当您处理浮点数学时,这只是生活中的一个事实。解决它的常用方法是完全避开等号,只执行 "numerically tolerant comparison",这意味着等于边界。所以这个检查:
a == b
将成为这张支票:
abs(a - b) < TOLERANCE
对于一些公差量。公差取决于您对输入的了解和计算机的精度;如果您使用的是 64 位计算机,您希望它至少是您将使用的最大数量的 1e-10
倍。例如,如果您要处理的最大输入约为 100,则使用 1e-8
.
的容差是合理的
我正在尝试在 Numpy 中执行一些不同的操作(mean
和 interp
),并且通过这两种操作我在不同的时间得到结果 2.77555756156e-17
,通常是我期待一个零。 即使尝试使用 array[array < 0.0] = 0.0
过滤掉这些值也无法删除这些值。
我假设是某种基础数据类型或环境错误导致了这种情况。数据应该都是浮点数。
编辑:有人指出,我只是过滤掉了 -2.77555756156e-17 的值,但仍然看到正数 2.77555756156e-17。问题的症结在于 什么可能导致这些古怪的值 在执行简单函数时出现,例如在 0-10 之间插值并取同一范围内的浮点数的平均值,以及如何才能我避免了它,而不必在每个语句后显式过滤数组。
您可以将您的值四舍五入为 15 位数字:
a = a.round(15)
现在数组 a
应该显示 0.0
个值。
示例:
>>> a = np.array([2.77555756156e-17])
>>> a.round(15)
array([ 0.])
这很可能是浮点运算错误的结果。例如:
In [3]: 0.1 + 0.2 - 0.3
Out[3]: 5.551115123125783e-17
不是您所期望的那样? Numpy 有一个内置的 isclose()
方法可以处理这些事情。此外,您可以使用
eps = np.finfo(np.float).eps
所以,也许这样的事情也能奏效:
a = np.array([[-1e-17, 1.0], [1e-16, 1.0]])
a[np.abs(a) <= eps] = 0.0
您运行正在研究数值精度,这是数值计算中的一个重要话题;当您使用浮点数进行任何计算时,您 运行 冒着 运行 变成微小值的风险,例如您在此处发布的值。发生的情况是您的计算产生的值无法完全用浮点数表示。
浮点数用固定数量的信息表示(在Python中,这个数量默认为64位)。您可以在非常好的 Floating point Wikipedia page 上阅读有关如何对信息进行编码的更多信息。简而言之,您在计算平均值的过程中执行的一些计算会产生无法精确表达的中间值。
这不是 numpy 的 属性(它甚至不是 Python 的 属性);它实际上是计算机本身的 属性。你可以在 repl 中查看这是正常的 Python:
>>> repr(3.0)
'3.0'
>>> repr(3.0 + 1e-10)
'3.0000000001'
>>> repr(3.0 + 1e-18)
'3.0'
对于最后的结果,您会期望 3.000000000000000001
,但该数字无法用 64 位浮点数表示,因此计算机使用最接近的近似值,在这种情况下只是3.0
。如果您尝试计算以下数字列表的平均值:
[3., -3., 1e-18]
根据您对它们求和的顺序,您可能会得到 1e-18 / 3.
,即 "correct" 答案,或者为零。你的处境有点陌生;您希望抵消的两个数字并没有完全抵消。
当您处理浮点数学时,这只是生活中的一个事实。解决它的常用方法是完全避开等号,只执行 "numerically tolerant comparison",这意味着等于边界。所以这个检查:
a == b
将成为这张支票:
abs(a - b) < TOLERANCE
对于一些公差量。公差取决于您对输入的了解和计算机的精度;如果您使用的是 64 位计算机,您希望它至少是您将使用的最大数量的 1e-10
倍。例如,如果您要处理的最大输入约为 100,则使用 1e-8
.