Python 避免";复数除零“;Numpy中的错误(与cmath相关)

Python 避免";复数除零“;Numpy中的错误(与cmath相关),python,numpy,divide-by-zero,cmath,Python,Numpy,Divide By Zero,Cmath,我希望避免在计算中使用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.) # Thi

我希望避免在计算中使用
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
,或者至少是一个中断计算的错误以外的任何东西。 第一个问题:我怎么做?

重要的是,我不想修改函数中的代码(例如,插入异常条件,如中所述),而是将其保持在当前形式(或者甚至删除
x=float_uux)
行,如果可能的话,如下所述)。 原因是我使用的是一个包含数十个函数的长代码:我希望它们都能避免
ZeroDivisionError
,而无需进行大量更改

我被迫插入
x=float_uux)
以避免
f(1.)中出现
ZeroDivisionError
第二个问题:是否有一种方法可以抑制这一行,但仍然得到
f(1.)=inf
,而不修改定义
f
的代码


编辑:

我意识到使用
cmath
来自cmath导入*
)是导致错误的原因。 没有它,我得到的是
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'.

问题:如何避免
零分区错误
不修改我函数的代码
g

我希望该函数能够自行处理错误,但如果不能,那么您可以在调用该函数时执行该操作(我认为这比修改函数要复杂得多)

或者,正如您提到的答案所示,使用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

出现错误的原因是您的程序正在使用
cmath
库中的
sqrt
函数。这是一个很好的例子,说明了为什么您应该避免(或至少要小心)使用
从库导入*
导入整个库

例如,如果反转导入语句,则不会出现问题:

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
,因为使用了
numpy
sqrt
函数(可以处理负数)。但这仍然是一种不好的做法:如果您有一个大文件,那么不清楚正在使用哪个
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 float与numpy float不同,因此这种转换需要在某个时候进行。

我仍然不明白为什么需要使用cmath。当您需要复杂输出时,请将cast
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
最终总是会给您提供复杂的输出,如果您将其结果反馈到
f
,这可能会导致问题,例如,因为现在该类型强制转换为float,等等。。。也许你应该在任何地方输入复杂的cast。但这将取决于你需要在更大范围内实现什么

编辑

事实证明,有一种方法可以让
g
仅在需要时返回复数。使用

这将提供您所期望的,仅在必要时转换为复杂

>>> f(1)
/usr/local/bin/ipython3:8: RuntimeWarning: divide by zero encountered in double_scalars
Out[1]: inf

>>> g(1)
/usr/local/bin/ipython3:12: RuntimeWarning: divide by zero encountered in double_scalars
Out[2]: inf

>>> g(-3)
Out[3]: -0.35355339059327379j

谢谢你的回答,但是这些选项并不是我真正想要的。正如您所说,第一个可能需要比修改函数本身更多的工作。请注意,在您给出的第二个备选方案中,
g(np.float(1.))
不起作用(我的代码已经包含
x=np.float(x)
g
的定义中,这产生了我报告的
ZeroDivisionError
)我得到一个警告,没有错误。谢谢你的帮助。在我的机器(Python2.7.10)中,如果没有包含cmath import*
中的
行,我会收到一条警告,但在编写时会收到错误。我的代码中需要这一行。请注意,我的问题是在插入
g(1.)
时获得
nan
(或至少不是错误),而不是
g(numpy.float_uu1.))
或任何其他选项。有没有解决我所寻找的问题的办法?我想你已经接近要点了。按照您的建议,我将
cmath
numpy
分别导入为
cm
np
。然而,我仍然有麻烦。我邀请你看一下我问题的第二部分。我真的很感激。你需要使用numpy sqrt函数。所以用
np.sqrt
替换
cm.sqrt
。不,因为正如我在注释(代码内部)中所说的,我希望为R-{1}中的所有x定义我的函数
g
:如果我使用
np.sqrt
,我得到
g(-3.)=nan
,我想得到
g(-3.)=-0.333
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.)
>>> f(1)
/usr/local/bin/ipython3:8: RuntimeWarning: divide by zero encountered in double_scalars
Out[1]: inf

>>> g(1)
/usr/local/bin/ipython3:12: RuntimeWarning: divide by zero encountered in double_scalars
Out[2]: inf

>>> g(-3)
Out[3]: -0.35355339059327379j