我希望在计算中避免使用ZeroDivisionError: complex division by zero
,在该例外情况下获取nan
。
让我用一个简单的例子来陈述我的问题:
from numpy import *
from cmath import *
def f(x) :
x = float_(x)
return 1./(1.-x)
def g(x) :
x = float_(x)
return sqrt(-1.)/(1.-x)
f(1.) # This gives 'inf'.
g(1.) # This gives 'ZeroDivisionError: complex division by zero'.
我打算获得g(1.) = nan
,或者至少是一个中断计算的错误。
第一个问题:我该怎么做?
重要的是,我不喜欢修改函数内部的代码(例如,插入异常条件,如this answer中所做的那样),而是将其保留在当前表格(如果可能,甚至删除x = float_(x)
行,如下所述)。
原因是我正在使用包含许多函数的长代码:我希望它们都能避免ZeroDivisionError
而不需要进行大量更改。
我被迫插入x = float_(x)
以避免ZeroDivisionError
中的f(1.)
。
第二个问题:是否有一种方法可以抑制此行但仍然可以f(1.) = inf
而不修改定义f
的所有代码?
编辑:
我已经意识到使用cmath
(from cmath import *
)会导致错误。
没有它,我得到g(1.) = nan
,这就是我想要的。
但是,我需要在我的代码中使用它。
所以现在第一个问题变成了以下内容:使用cmath
时如何避免“复杂除零”?
编辑2:
在阅读答案之后,我做了一些改变,我简化了问题,越来越接近这一点:
import numpy as np
import cmath as cm
def g(x) :
x = np.float_(x)
return cm.sqrt(x+1.)/(x-1.) # I want 'g' to be defined in R-{1},
# so I have to use 'cm.sqrt'.
print 'g(1.) =', g(1.) # This gives 'ZeroDivisionError:
# complex division by zero'.
问题:如何避免ZeroDivisionError
不修改我的函数代码g
?
答案 0 :(得分:1)
我希望函数能够自己处理错误,但如果没有,那么你可以在调用函数时这样做(我相信这比修改函数更有用)。
try:
f(1.) # This gives 'inf'.
except ZeroDifivisionError:
None #Or whatever
try:
g(1.) # This gives 'ZeroDivisionError: complex division by zero'.
except ZeroDifivisionError:
None #Or whatever
或者,正如您所提到的答案所述,请使用numpy数字调用您的函数:
f(np.float_(1.))
g(np.float_(1.))
=======
在我的机器上,这个确切的代码给了我一个警告,没有错误。
我不认为有可能得到你想要的东西而不会发现错误......
def f(x):
return 1./(1.-x)
def g(x):
return np.sqrt(-1.)/(1.-x)
print f(np.float_(1.))
>> __main__:2: RuntimeWarning: divide by zero encountered in double_scalars
>>inf
print g(np.float_(1.))
>> __main__:5: RuntimeWarning: invalid value encountered in sqrt
>>nan
答案 1 :(得分:1)
我仍然不明白为什么你需要使用cmath。如果期望复杂输出,请在x
内输入np.complex_
,然后使用np.sqrt
。
import numpy as np
def f(x):
x = np.float_(x)
return 1. / (1. - x)
def g(x):
x = np.complex_(x)
return np.sqrt(x + 1.) / (x - 1.)
这会产生:
>>> f(1.)
/usr/local/bin/ipython3:3: RuntimeWarning: divide by zero encountered in double_scalars
# -*- coding: utf-8 -*-
Out[131]: inf
>>> g(-3.)
Out[132]: -0.35355339059327379j
>>> g(1.)
/usr/local/bin/ipython3:3: RuntimeWarning: divide by zero encountered in cdouble_scalars
# -*- coding: utf-8 -*-
/usr/local/bin/ipython3:3: RuntimeWarning: invalid value encountered in cdouble_scalars
# -*- coding: utf-8 -*-
Out[133]: (inf+nan*j)
当然,缺点是函数g
将总是最终为您提供复杂的输出,如果您将其结果反馈回{{1},这可能会导致问题例如,因为 现在类型转换为浮动,依此类推......也许你应该只是在任何地方输入复制。但这取决于你需要在更大规模上实现的目标。
修改强>
事实证明,只有在需要时才能让f
返回复合体。使用numpy.emath
。
g
这现在可以提供你所期望的,只在必要时转换为复合体。
import numpy as np
def f(x):
x = np.float_(x)
return 1. / (1. - x)
def g(x):
x = np.float_(x)
return np.emath.sqrt(x + 1.) / (x - 1.)
答案 2 :(得分:0)
出现错误是因为您的程序正在使用sqrt
库中的cmath
函数。这是一个很好的例子,说明为什么你应该避免(或者至少要小心)使用from library import *
导入整个库。
例如,如果你反转import语句,那么你就没有问题了:
from cmath import *
from numpy import *
def f(x):
x = float_(x)
return 1./(1.-x)
def g(x) :
x = float_(x)
return sqrt(-1.)/(1.-x)
现在g(1.)
会返回nan
,因为sqrt
使用numpy
函数(可以处理负数)。但这仍然是不好的做法:如果你有一个大文件,那么不清楚使用哪个sqrt
。
我建议始终使用import numpy as np
和import cmath as cm
等命名导入。然后,不会导入函数sqrt
,要定义g(x)
,您需要编写np.sqrt
(或cm.sqrt
)。
但是,您注意到您不想更改您的功能。在这种情况下,您只应从您需要的每个库中导入这些函数,即
from cmath import sin # plus whatever functions you are using in that file
from numpy import sqrt, float_
def f(x):
x = float_(x)
return 1./(1.-x)
def g(x) :
x = float_(x)
return sqrt(-1.)/(1.-x)
不幸的是,你不能轻易摆脱转换为numpy float_
,因为python浮点数与numpy浮点数不同,所以这种转换需要在某个时刻发生。