在代码中引发的错误,根据懒惰的评估不应该运行 [英] Error raised in code that shouldn't run according to lazy evaluation

查看:67
本文介绍了在代码中引发的错误,根据懒惰的评估不应该运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将以下代码作为函数的一部分:

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

它并非在所有情况下都有效,但是可能会发生这种情况,因为仅当pxpy都为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最终将infnan放入返回数组中.因此,您仍然需要测试(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆