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)