匿名函數和嵌套函數能很方便的表示所求方程,供fsolve等求解函數調用
eg.1 求解如下二維非線性方程組
% 匿名函數方法
clear,clc
f = @(x)[exp(-exp(-(x(1)+x(2))))-x(2)*(1+x(1)^2);...
x(1)*cos(x(2))+x(2)*sin(x(1))-1/2];
[x,fval,exitflag,output] = fsolve(f,[0,0]);
disp(['方程的解為:x1 = ',num2str(x(1)),',x2 = ', num2str(x(2))]);
運行結果如下:
% 局部函數方法
clear,clc
[x,fval,exitflag,output] = fsolve(@myfun,[0,0]);
disp(['方程的解為:x1 = ',num2str(x(1)),',x2 = ', num2str(x(2))]);
%
function f1 = myfun(x)
f1 = zeros(2,1);
f1(1) = exp(-exp(-(x(1)+x(2))))-x(2)*(1+x(1)^2);eg.2 求解方程
,其中a在[0, 2]中變化
%% 匿名函數表示含參方程
% 使用向量化函數arrayfun求解
clear,clc
f = @(a)@(x)exp(x)+x^a+x^(sqrt(x))-100; % 構造含參函數句柄
aa = [0:0.1:2];
f1 = @(a)fsolve(f(a),10); % 構造arrayfun函數可輸入的函數句柄
X = arrayfun(f1,aa);
% 繪製不同a對應方程解x的對應關係
fig1 = figure;
line1 = plot(aa,X,'-k','LineWidth',1.5);
xlabel('\ita','Interpreter','tex','FontName',...
'Times New Roman','FontSize',15);
ylabel('\itx','Interpreter','tex','FontName',...
'Times New Roman','FontSize',15);
title('\ite^{x}+x^{a}+x^{\surdx}-100','Interpreter','tex',...
'FontName','Times New Roman');
運行結果:
%% 局部函數方法
clear,clc
aa = [0:0.1:2];
f2 = @(a)fsolve(@(x)myfun(x,a),10); % 構造arrayfun函數可輸入的函數句柄
% 多重匿名函數形式外層變量@(a)作用整個'fsolve(@(x)myfun(x,a),10)'語句
% 內層變量@(x)作用'myfun(x,a)'語句
X = arrayfun(f2,aa);
% 繪製不同a對應方程解x的對應關係
fig = figure;
line1 = plot(aa,X,'-k','LineWidth',1.5);
xlabel('\ita','Interpreter','tex','FontName',...
'Times New Roman','FontSize',15);
ylabel('\itx','Interpreter','tex','FontName',...
'Times New Roman','FontSize',15);
title('\ite^{x}+x^{a}+x^{\surdx}-100','Interpreter','tex',...
'FontName','Times New Roman');
% -
function f1 = myfun(x,a)
f1 = exp(x)+x^a+x^(sqrt(x))-100;
end2. 隱函數顯式表達隱函數在數學上無法顯式表示,但可通過構造匿名函數來數值表達:對於給定的自變量可通過數值方法隨時求解因變量
eg.3 顯式表達 y關於 x的隱函數
f = @(x)fsolve(@(y)(exp(y)+x^(y))^(1/y)-x^2*y,2);
disp(['當x = 1時,y = ', num2str(f(1))]);
此時f只接受標量x的輸入(fsolve這類函數只能進行標量計算),使用arrayfun實現向量化輸入
F = @(x)arrayfun(@(xx)fsolve(@(y)(exp(y)+xx^(y))^(1/y)-xx^2*y,2),x);
disp(['當x分別取[',num2str([1:5]),']時,y = [',num2str(F([1:5])),']']);
eg.4 顯式表示下列z關於x,y的隱函數
% 使用局部函數構造子函數
f = @(x,y)fsolve(@(z)myfun(x,y,z), 1);
% 初值>0時得到的是z大於0的解,初值<0時可達到z小於0的解
xx = [-5:0.5:5];yy = [-5:0.5:5];
[X,Y] = meshgrid(xx,yy);
Z = arrayfun(f,X,Y);
figure;
fig1 = surf(X,Y,Z);
fig1.EdgeColor = 'none';fig1.FaceAlpha = 0.5;
title('通過函數計算得到')
% 使用三維隱函數繪圖函數fimplicit3繪製對比
f = @(x,y,z)x.^2+y.^2-z.^2;
interval = [-5 5 -5 5 0 7];
figure;
fig2 = fimplicit3(f,interval);
fig2.EdgeColor = 'none';fig2.FaceAlpha = 0.5;
title('使用三維隱函數繪圖函數fimplicit3得到')
%
function f = myfun(x,y,z)
f = x^2+y^2-z^2;
end運行結果:
3. 函數在表示高階微分方程組中的應用eg.5 求解微分方程
在[0,5]範圍的解
首先將高階微分方程轉化為一階微分方程組:
令
則原微分方程可轉化為如下微分方程組
% 使用嵌套函數進行求解
qiujie(3);
function qiujie(a)% 不同的參數a可輸出不同的結構
tspan = [0,5];
y0 = [1,1];
[t,y] = ode45(@dydt,tspan,y0);
figure;
line1 = plot(t,y(:,1),'-k','LineWidth',1.5); % 繪製y(t)曲線
hold on
line2 = plot(t,y(:,2),'--r','LineWidth',1.5); % 繪製y(t)導數曲線
hold off
lgd = legend;
set(lgd,'String',{'\ity', '\rmd\ity'},'FontName','Times New Roman','FontSize',15);
xlabel('\itt','FontName','Times New Roman','FontSize',15);
ylabel('\ity \rmand \rmd\ity','FontName','Times New Roman','FontSize',15);
% 使用嵌套函數定義微分方程組
function f = dydt(t,y)
f = zeros(2,1);
f(1) = y(2);對於比較簡單的方程形式,也可使用匿名函數進行表示
qiujie(3);
function qiujie(a)
f = @(t,y)[y(2);3*sin(a*t)-4*y(1)]; % 構造匿名函數
當 a = 3 時的運行結果為:
4. Matlab將符號表達式轉化為函數句柄進行數值計算在用符號(symbolic)運算得到一個符號表達式後,我們可能需要令其進一步參與數值運算。然而,很多數值運算函數,比如數值積分函數(quad,quadgk,integral)都只能接受函數句柄作為輸入。於是,將符號表達式轉化為函數句柄就成了必然。
如果不怕麻煩,完全可以通過手動輸入對應的符號表達式來建立函數句柄。然而,很多情況下我們得出的符號表達式可能極其複雜,甚至可能佔據很多行。此時,手動輸入顯然相當不便。於是,找到一種自動將符號表達式轉化為函數句柄的方法就顯得尤為重要。下面列舉出三種自動轉換的辦法:
clear,clc
syms x
y = exp(x)*x^2+x+1;
g = matlabFunction(y)
disp(['使用matlabFunction轉化得到的匿名函數為:g = ',func2str(g)]);
disp(['當x取x = 2時, g(2) = ', num2str(g(2))]);
format long;
X = fsolve(g,1);
disp(['方程',char(y),'的解為x = ',num2str(X)]);
vectorize的目的是將字符串(string)表達式裡的* / ^替換為.* ./ .^,以支持向量運算
cdot = vectorize(c)
%c為字符向量、字符串標量
eval(expression)
% expression 為字符向量和字符串標量是要計算的表達式
clear,clc
syms x
y = exp(x)*x^2+x+1;
g = eval(['@(x)' vectorize(y)]) % 執行構造函數句柄的操作
disp(['使用eval+vectorize轉化得到的匿名函數為:g = ',func2str(g)]);
disp(['當x取x = 2時, g(2) = ', num2str(g(2))]);
clear,clc
syms x
y = exp(x)*x^2+x+1;
g = str2func(['@(x)' vectorize(y)])
disp(['使用str2func+vectorize轉化得到的匿名函數為:g = ',func2str(g)]);
disp(['當x取x = 2時, g(2) = ', num2str(g(2))]);
matlab求解函數(fsolve、ode45)等接收的都是以x向量為自變量的方程或方程組,符號推導過程中的方程組變量x1,...xN需要表示成x = [x(1),...,x(N)]的向量形式。
clear,clc
syms x1 x2
y = 2*x1-x2-exp(-x1);
z = -x1+2*x2-exp(-x2);
g = matlabFunction([y;z],'Vars',[x1 x2]) % 以x1和x2為自變量的匿名函數
f = @(x)g(x(1),x(2)); % 構建以x向量為自變量的匿名函數句柄,x1 = x(1), x2 = x(2)
fsolve(f,[0,1])