http://www.ilovematlab.cn/thread-260310-1-1.html
http://blog.sina.com.cn/s/blog_66faf9cf0101ckuu.html
在用符号 (symbolic) 运算得到一个符号表达式后,我们可能需要令其进一步参与数值运算。然而,很多数值运算函数,比如数值积分函数(quad,quadgk,integral),都只能接受函数句柄作为输入。于是,将符号表达式转化为函数句柄就成了必然。
如果不怕麻烦,完全可以通过手动输入对应的符号表达式来建立函数句柄。然而,很多情况下我们得出的符号表达式可能极其复杂,甚至可能占据很多行。此时,手动输入显然相当不便。于是,找到一种自动将符号表达式转化为函数句柄的方法就显得尤为重要。下面列举出三种自动转换的办法(三种办法得到的函数都是匿名函数):
1. 最简便的办法:利用 matlabFunction(这个函数只适用于2009a及更新的版本)
- syms x
- y=exp(x)*x^2+x+1
- g = matlabFunction(y)
如果你的matlab报错,这说明你的版本太老,那么请使用下面两种办法。
2. eval + vectorize 函数:vectorize 的目的是将字符串(string)表达式里的 * / ^ 替换为 .* ./ .^ ,以支持向量运算。eval 执行该字符串后得到函数句柄
- syms x
- y=exp(x)*x^2+x+1
- g = eval_r(['@(x)',vectorize(y)])
这个方法需要借助 eval 函数,在论坛里已经被广大坛友广泛使用过。
3. str2func + vectorize 函数:str2func 函数可以直接将字符串转化为函数句柄
- syms x
- y=exp(x)*x^2+x+1
- g = str2func(['@(x)',vectorize(y)])
这两天重新 review 了一下 matlabFunction,发现这个函数其实是很强大的,特意来对 16 楼的办法做一点补充。
matlabFunction 可以在将多个符号表达式转换为向量化函数(这一转换的目的是为了供fsolve等函数使用),即函数输入是一个向量化参数,函数返回值也是一个向量化返回值。实现这一转换只需在matlabFunction调用时使用 'vars' 参数,并将多个自变量合写成一个向量并放在 {} 里。这个转换是一步即可完成,很方便。而我之前在 16 楼提供的办法实际上是分两步转换的:第一步是将多个函数返回值转换为一个向量化函数返回值,第二步是将多个输入自变量转换为一个向量化输入参数。显然 16 楼的办法没有直接用 'vars' 参数转换来得快。
现在还是以我在 16 楼的例子来说明这个问题。
- syms x1 x2;
- y = 2*x1 - x2 - exp(-x1);
- z = -x1 + 2*x2 - exp(-x2);
- % 16 楼的旧方法,分2步实现
- f1 = matlabFunction([y;z]);
- f1 = @(x) f1(x(1),x(2));
- fsolve(f1,[0 1])
- % 新方法:直接利用 'vars' 参数一步转换成功
- f2 = matlabFunction([y;z], 'vars', {[x1 x2]});
- fsolve(f2,[1 1])
运行后会发现两种方法得到了相同的结果。显然,新方法更为简洁。
另外一个例子:
- syms t
- y=sin(2*t).*exp(-0.5*t);
- dy = diff(y);
- dyf = matlabFunction(dy);
- t = [0:0.01:5];
- plot(t,subs(y));
- x0 = [1,2,4];
- x = arrayfun(@(x0) fzero(dyf,x0), x0)