arg和atan2之间差异的原因

时间:2014-11-11 13:52:30

标签: python sympy complex-numbers

最近,我使用sympy和cos(x)作为一个复杂的函数,发现提供的参数函数argatan2函数会产生不同的结果。通过绘制结果可以很容易地显示出来。

import sympy as sp
c = sp.cos(x)
sp.plot(sp.atan2(sp.im(c),sp.re(c)))
sp.plot(sp.arg(c))

enter image description here

虽然差异只是pi的自然倍数,但我希望这两个函数都能返回上图。这也是WolframAlpha产生的结果,请参阅argatan2。 有趣的是,如果我在数值上计算参数(使用sympy函数),我得到了预期的结果:

import numpy as np
import matplotlib.pyplot as plt
xv = np.linspace(-10,10,200)
plt.plot(xv,[sp.arg(i) for i in np.cos(xv)])

enter image description here

有人可以,请指出差异,也许是一个合理的解决方案,以获得相同的结果?

我使用了sympy 0.7.5。

2 个答案:

答案 0 :(得分:3)

不同的情节来自于同情中的优化。当你绘制一些东西时,sympy在内部使用numpy来评估你的功能。 sympy的函数vectorized_lambdifyarg(cos(x))转换为它的numpy等价物,np.angle(np.cos(x)),然后sympy会为适当的numpy数组求值。所以同情的事情大致相当于

import numpy as np
import matplotlib as plt

xv = np.array(np.linspace(-10,10,200), dtype=np.complex)
plt.plot(xv, np.angle(np.cos(xv)))

这会重现从-pi到pi的跳转。有关sympy中重要的代码行,请参阅here

使用atan的另一个变体被重写为

np.arctan2(-np.sin(np.real(x))*np.sinh(np.imag(x)), 
            np.cos(np.real(x))*np.cosh(np.imag(x)))

相当于numpy的definition of angle,并且确实绘制了这个也是跳跃的特征。因此,从我的角度来看,更重要的问题是:为什么sp.atan2(..)的情节看起来不同?

我还没有找到原因,但我相信这可能会超出你问题的范围?!回答你的问题:

  • 只要您在同意中使用符号版本,您所做的一切都是正确的, 等效
  • 如果你想得到相同的结果,最简单的版本可能是绘制模2pi。或者,通过直接从numpy绘制类似experimental_lambdify的内容来避免lambda val: (expr).subs(x, val)调用,或者完全替换lambdify:在运行第一个示例之前执行以下代码,两个绘图看起来都像上面的那样:

    import sympy.plotting.experimental_lambdify
    sympy.plotting.experimental_lambdify.experimental_lambdify = lambda x, exp, **kwargs: vectorize(lambda val: exp.subs(x[0], val))

    (请注意,此版本的代码段仅适用于1d图。)

答案 1 :(得分:0)

这可能是预期的行为。参数通常被认为是从-pi到pi,因为复平面中的分支切割发生在负实轴而不是正实轴