假设你有一个由区间定义的函数,例如
f(x):=block(if x<0 then x^2 else x^3);
当我们区分它时
diff(f(x),x);
我们得到
d/dx (if x<0 then x^2 else x^3)
而我想得到
(if x<0 then 2*x else 3*x^2)
有没有办法获得这样的结果?
这是一种不同的方法,使用“if”表达式的简化规则。这里未解决的部分是检测不连续性并为这些位置生成增量函数。如果你想忽略这些,你可以定义
FOO
返回 0。请注意,我并没有尝试实现函数 discontinuities
;这部分在这里没有解决。有兴趣的话我可以尝试一下。
(%i1) display2d : false $
(%i2) matchdeclare ([aa, bb, cc], all, xx, symbolp) $
(%i3) 'diff (if aa then bb else cc, xx) $
(%i4) tellsimpafter (''%, apply ("if", [aa, diff (bb, xx), true, diff (cc, xx)]) + FOO (aa, bb, cc, xx)) $
(%i5) FOO (a, b, c, x) := 'lsum ((ev (c, x = d) - ev (b, x = d)) * delta (d, x), d, discontinuities (a, x)) $
(%i6) diff (if x > 0 then x^2 else x^3, x);
(%o6) (if x > 0 then 2*x else 3*x^2)+'lsum((d^3-d^2)*delta(d,x),d,
discontinuities(x > 0,x))
在slitinov的答案的基础上,我为具有两个以上“部分”的函数编写了这个相当幼稚的实现:
gradef(charfun(dummy),0)$
/* piecewise function definition */
itv: [[x<0],[x>=0,x<1], [x>=1]]; /* intervals */
fi: [ 1, x^2+1, 2*x ]; /* local functions */
/* creation of global function f and its derivative df */
f:0;
for i: 1 thru 3 do f:f+charfun(apply("and",itv[i]))*fi[i];
df:diff(f,x);
/* display of local functions and derivatives */
for i: 1 thru 3 do (
apply(assume,itv[i]),
newline(),
print(itv[i]),
print("f = ",ev(f)),
print("df = ",ev(df)),
apply(forget,itv[i])
);
plot2d([f,df],[x,-2,3],[y,-1,5],[style,[lines,4,3],[lines,2,2]]);
另一种更直接且正确处理不连续性导数的替代方法是使用
hstep(x)
(Heaviside) 函数。
假设你想定义一个函数,如:
f(x):=if(is(abs(x)<1)) then x^2 else sin(x);
使用
hstep
的替代定义是:
f(x):= hstep((x+1)*(x-1)) * x^2 + hstep( -(x+1)*(x-1) )*sin(x);
这给出了适当的导数作为
delta
:
diff(f(x), x);
2 x hstep((x - 1) (x + 1)) + 2 x delta((x - 1) (x + 1))
+ cos(x) hstep((1 - x) (x + 1)) - 2 x sin(x) delta((1 - x) (x + 1))