抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

这篇文章主要是记录一下在回答贴吧上这个问题时所发现的关于Mathematica求导的一些坑。

原问题虽然没有明说,但我推测问题背景应该是波特图之类的问题,具体问题如下:

对这个函数的幅角求导,代入一个数值为什么求出了个复数值啊,实函数求导应该是实数啊。声明了一下x是实数后好像也不行。

1
2
3
4
5
f[x_] := Arg[(-(x - 1)^2 + 4 (4 x^3 - 3 x^2 - x^4))/((x - 1)^2 + 4 (4 x^3 - 3 x^2 - x^4) - 4*I*(x^3 - 3 x^2 + 2 x))]
f'[5]
(*Out: (513125/13791752+(342351 I)/3447938) Arg'[2499/2626-(765 I)/2626]*)
N[(513125/13791752+(342351 I)/3447938) Arg'[2499/2626-(765 I)/2626]]
(*Out: 0.0109427 + 0.0292034 I*)

这是程序,我觉得可能是程序表达的问题,那么该怎么去写这个程序呢?新手上路,老哥请指点

这段程序恰好碰到了Mathematica在求导问题上的两个坑:

  1. Mathematica总是假设链式求导法则是有效的,但这里遇到的Arg本身是一个不可导的函数,链导法则是不成立的。这一点是一个非常常见的坑。
  2. 然后Mathematica的数值导数设计的也欠合理,在遇到符号求导失效的情况时,Mathematica在计算函数导数时会利用其沿着实轴方向的变化率来近似求导(事实上Arg沿复平面不同方向的变化率通常不相等),而Arg本身总是实数,这样一来得到的Arg'[...]的结果就总是一个实数,然而前面根据链导法则乘出的那一坨又是个复数,自然得到的最终结果也是复数。

针对这个问题,可以提出两种解决办法:

  1. 一个很自然的想法是直接绕开Arg这个不可导的函数,即可以将通过ComplexExpand其转化为ArcTan形式,再去求导就不会有这些问题了:
    1
    2
    3
    f[x_]=ComplexExpand[Arg[(-(x-1)^2+4 (4 x^3-3 x^2-x^4))/((x-1)^2+4 (4 x^3-3 x^2-x^4)-4*I*(x^3-3 x^2+2 x))],TargetFunctions->{Re,Im}];
    f'[5]
    (*Out: 1117/10504*)
  2. 还可以反过来利用上述数值导数的坑来解决:因为这里就是要求f沿实轴方向的导数,所以我们不妨利用数值导数始终沿实轴发生这一特性,先从f上就避免符号计算引入错误的链导法则,然后直接让Mathematica对f进行数值求导,于是可以这么写:
    1
    2
    3
    4
    Clear[f]
    f[x_?NumericQ]:=Arg[(-(x-1)^2+4 (4 x^3-3 x^2-x^4))/((x-1)^2+4 (4 x^3-3 x^2-x^4)-4*I*(x^3-3 x^2+2 x))]
    f'[5.]
    (*Out: 0.10634*)
    如果只需要近似的数值值得话,同样可以解决问题。

相关链接:

评论