在代码中引发的错误,根据懒惰的评估不应该运行 [英] Error raised in code that shouldn't run according to lazy evaluation
问题描述
我将以下代码作为函数的一部分:
I have the following code as part of a function:
px = x2 - x1
py = y2 - y1
pz = z2 - z1
div = px*px + py*py
u = ((x0 - x1) * px + (y0 - y1) * py) / div
u=
行在运行时返回RuntimeWarning: invalid value encountered in divide
.这是因为div=
行偶尔返回零.
the u=
line returns RuntimeWarning: invalid value encountered in divide
when run. This is because occasionally the div=
line returns zero.
但是,如果我将u=
行改写为:
However, if I rewrite the u=
line as:
u = np.where(div != 0, ((x0 - x1) * px + (y0 - y1) * py) / div, 0)
它仍然返回相同的运行时警告.
it still returns the same runtime warning.
此代码输出所需的数字,但是我认为np.where
函数是惰性的.如果不是这种情况,那么我编写的其他代码可能会加快速度(因此,我要问这个问题).
我想念什么? np.where
函数会同时计算"True"和"False"输入,然后根据布尔值选择一个吗?
This code outputs the desired numbers however I thought that the np.where
function was lazy. If this is not the case then there are potential speed ups in other bits of code I have written (hence I'm asking this question).
What am I missing? Does the np.where
function calculate both the 'True' and 'False inputs and then select one depending on the boolean?
注意,这是我最终得到的解决方案:
Note, this is the solution I've ended up with:
np.seterr(invalid='ignore')
u = np.where(div != 0, ((x0 - x1) * px + (y0 - y1) * py) / div, 0)
np.seterr(invalid='warn')
尽管这也很好:
u = np.zeros_like(div)
divb = div != 0
u[divb] = ((x0[divb] - x1[divb]) * px[divb] +
(y0[divb] - y1[divb]) * py[divb]) / div[divb]
(这是我以为np.where
所做的...)
(which is kind of what I thought np.where
did...)
这两种解决方案的速度大致相同,但都比np.where
函数慢.
Both these solutions are around the same speed but both are slower than just the np.where
function on its own.
欢迎任何解释/建议! 谢谢.
Any explanations/suggestions welcome! Thanks.
推荐答案
这是自最早的矢量化语言(例如APL,MATLAB)以来程序员一直在解决的除以零"的问题.
This is a divide by 0 issue that programmers have been working around since the earliest vectorized languages (e.g. APL, MATLAB).
我过去使用的一种解决方案是(有条件地)将除数加1:
One solution which I've used in the past is to (conditionally) add 1 to the divisor:
u = ((x0 - x1) * px + (y0 - y1) * py) / (div + (div==0))
它并非在所有情况下都有效,但是可能会发生这种情况,因为仅当px
和py
都为0时,div
才为0.在这种情况下,分子也为0. 0/1 = 0
.
It doesn't work in all cases, but it might in this, since it appears the div
will be 0 only if both px
and py
are 0. In that case the numerator is also 0. 0/1 = 0
.
或以较小的值裁剪div
(这可能是最快的解决方案):
Or clipping div
with a small value (this may be the fastest solution):
..../np.maximum(div,1e-16)
在SO上快速搜索numpy divide by zero
时发现了其他问题.例如:
A quick search on SO for numpy divide by zero
turned up other questions. For example:
https://stackoverflow.com/a/26248892/901925
建议使用errstate
上下文关闭警告:
https://stackoverflow.com/a/26248892/901925
suggests using errstate
context to turn off the warning:
with numpy.errstate(divide='ignore'):
u = .../div
divide
适用于类似1/0
的情况,而invalid
对于0/0
情况是必需的.但是ignore
最终将inf
或nan
放入返回数组中.因此,您仍然需要测试(div==0)
以获得0
值.
divide
works for cases like 1/0
, while invalid
is needed for 0/0
cases. But ignore
ends up putting either inf
or nan
in the return array. So you still need to test for (div==0)
to get a 0
value.
尽管我更喜欢这种形式的外观:
Though I rather like the appearance of this form:
with np.errstate(invalid='ignore'):
u = np.where(div==0, 0, .../div)
Warren的评论解释了为什么where
不起作用.在传递给函数之前先对参数求值.惰性求值需要Python解释器的配合.通常是语法的一部分(例如if
,|
,&
).
Warren's comment explains why where
doesn't work. The arguments are evaluate before being passed to the function. Lazy-evaluation requires the cooperation of the Python interpreter. It is normally part of the syntax (e.g. if
,|
,&
).
这篇关于在代码中引发的错误,根据懒惰的评估不应该运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!