제 9 장 함수
익명함수 MATLAB 7 에서도입된익명함수 (anonymous function) 를이용하면 M- 파일을작성하지않고 한줄 함수를생성가능 >> f = @(x) exp(x)-1 f = @(x) exp(x)-1 >> f(2) ans = 6.3891 위에서 f 는익명함수에대한함수핸들 함수핸들을구성하는 @ 기호다음에는괄호안에함수에대한입력인수들이위치하며다음 에하나의 MATLAB 표현이이어짐 함수핸들이므로익명함수는다른함수들에전달가능 익명함수를계산하는문장은인수목록에는없는변수들을포함가능 함수가생성될때그러한변수들의값이취하여지며다음의 3- 인수함수에대한예에서알 수있듯이이값들은함수의수명동안일정하게유지
>> alpha = 1; >> g = @(x,y,z) x^2+y^2-alpha*z^2; >> g(1,2,3) ans = -4 >> alpha = 0; >> g(1,2,3) ans = -4 alpha 의달라진값이 g 에반영되기위해서는익명함수가재구성되어야함 명령어 eval 은문자열로저장된명령어를마치명령어라인에서그문자열을입력한것처럼 수행가능 예를들어 eval('cos(1)') 을입력하면 cos(1) 을입력한경우와동일한결과 수행하고자하는전체명령어가문자열 str 에포함되어있다면 eval(str) 에의하여이를수행 가능 eval 은익명함수에대한입력들의수에약간의유연성을허용
다음과같은명령어는두개나세개의입력인수들을더하여주는익명함수를생성 >> add = @(x, y, z) eval('x+y+z', 'x+y') 명령어 deal 을이용하여다수의출력을갖는익명함수생성가능 >> rectangular = @(r,theta) deal(r.*cos(theta), r.*sin(theta)) 위와같이입력하면한쌍의극좌표를한쌍의직교좌표로전환시켜주는함수가생성
함수핸들 MATLAB을이용하는많은문제들에서는하나의함수가다른함수에인수로제공되는것이필요 통상적인방법은함수핸들을사용 함수핸들은하나의 MATLAB 데이터형식으로서함수를계산하는데에필요한모든정보를포함 함수핸들은함수이름앞에 @ 기호를넣어생성 범위 [ ] 에서함수 f(x) 의그래프를그리는 ezplot를이용한함수핸들의사용을예시 만일 fun이 ezplot에서필요로하는형태의함수 M-파일이라면다음과같이사용가능 ezplot(@fun) fun은 M-파일은물론내장함수의이름일수도있음 ezplot(@sin)
다른함수를인수로받아들이는함수는전달된함수를계산할필요가있으므로함수핸들을단순히함수이름으로간주하고여기에인수목록을붙여줌으로써간단히계산함 호출되는함수가입력인수를필요로하지않으면함수핸들이름다음에빈괄호를넣어줌함수 M-파일 fd.m은첫번째인수로제공된함수에대한유한차분근사를계산 % fd.m : 미분에대한유한차분근사. function y = fd(f,x,h) if nargin < 3, h = sqrt(eps); end y = (f(x+h) - f(x))/h; 이함수의수행예시 >> fd(@sqrt,0.1) ans = 1.5811
함수핸들은어떤함수를다른함수로의입력인수로지정하는데있어서선호되는방법 M- 파일 iterate.m 은함수핸들 ( 혹은인라인함수 ) 과초기값을입력하여지정된횟수만큼그 함수를반복계산 function v = iterate(func, init, num) v = init; for k = 1:num v = func(v); end 내장함수나함수 M- 파일의이름앞에 @ 기호를두는것은그함수에대한핸들생성 iterate(@cos, 1, 2) 는 cos(cos(1)) 의수치값을계산하며 iterate(@cos, 1, 100) 은 cos(x)=x 인실 수 x 에대한근사를제시 >> iterate(@cos, 1, 2) ans = 0.8576 >> iterate(@cos, 1, 100) ans = 0.7391
인라인객체 수학적함수를 MATLAB 함수에전달하는방법으로서인라인객체를이용 인라인객체들은 MATLAB 6 에서처음도입되었으며 MATLAB 7 에서도입된보다다양하고 효율적인익명함수들에의하여대체 인라인객체는사실상문자열로정의되는 한줄 함수로서변수에할당된다음에다른함수 로전달가능 f 는함수핸들이아님을유의 >> f = inline('exp(x)-1') f = Inline function: f(x) = exp(x)-1 >> f(2) ans = 6.3891 MATLAB 은인라인함수에대한인수들을자동적으로결정하고순서를정함
그선택이적절하지않으면 inline 에대한추가의인수들을통하여인수들이구체적으로정의 되고순서가정해짐 >> f = inline('log(a*x)/(1+y^2)') f = Inline function: f(a,x,y) = log(a*x)/(1+y^2) >> f = inline('log(a*x)/(1+y^2)','x','y','a') f = Inline function: f(x,y,a) = log(a*x)/(1+y^2) 때로는인라인객체나문자열표현을벡터화하는것이필요 (vectorize 함수에의하여생성 ) >> f = inline('log(a*x)/(1+y^2)'); >> f = vectorize(f) f = Inline function: f(a,x,y) = log(a.*x)./(1+y.^2)
부함수 함수 M- 파일의첫번째줄에나타나는것외에명령어 function 은추가로 M- 파일의뒷부분 에서보조함수, 혹은부함수의정의에사용 부함수는 M- 파일내의어느곳에서도사용될수있지만명령어라인에서직접접근불가 부함수들은대체적으로주함수와분리될필요가있지만다른 M- 파일들에서는필요할것같 지않은기능을수행하며혹은동일한이름을갖는기존함수들에겹쳐질수도있음 함수 M- 파일 sumcubr.m 은실수벡터 x 의세제곱근을합하고있음 function y = sumcubr(x) y = sum(cuberoot(x)); % --- 여기에서부함수가시작 function z = cuberoot(x) z = sign(x).*abs(x).^(1/3); 수행결과 >> sumcubr(100) ans = 4.6416
부함수 cuberoot 는 x 의세제곱근을원소마다취하며, 부함수는스크립트 M- 파일이아닌함 수 M- 파일에서만이용가능 interr.m 에서는구간 [0,1] 에서 n 개의샘플에근거하는부함수 f 에대한선형안짐작다항식의 최대오차를근사 % interr.m: 선형안짐작다항식의오차. function maxerr = interr(n) maxerr = 0; f0 = f(0); f1 = f(1); for x = linspace(0,1,n) p = x*f1 + (x-1)*f0; err = abs(f(x)-p); maxerr = max(maxerr,err); end % 부함수 function y = f(x) % f(x): 안짐작되는함수 y = sin(x); 수행결과 >> interr(5) ans = 0.0587 >> interr(40) ans = 0.0600
기본적인입력인수 : nargin nargin(number of argument of Input) 을사용하여특별한호출에서그입력인수들가운데 처음몇개만이공급되고그나머지인수들은함수내에서기본값으로설정되도록함수를작 성가능 함수를구성할때에는그의입력인수들을중요도가높은것부터낮은순위대로공급되어야 하는순서에따라지정할수있거나없는것들과함께정렬시켜야함 M- 파일 exfun.m function f = exfun(a, np, na, step) if nargin < 2 isempty(np), np = length( A); end if nargin < 3 isempty(na), na = 10; end if nargin < 4, step = 0.1; end 배열 A 는반드시제공되어야하지만다른인수들은임의적 함수 exfun.m 은다음과같이호출가능 A = 1:0.5:8; exfun(a,10,20,1e-3) exfun(a,10) exfun(a,[],50) exfun(a,[],[],0.5) 빈행렬 [] 가두번째나세번째인수로제공되면해당되는 if 테스트의 isempty 부분은기본 값이관련되는변수에부여됨
가변적인인수의개수 : varargin 과 varargout 어떤경우에는함수가제한이없을수도있는가변적인수의입력이나출력인수들을받아들이거나반환해야함 varargin 및 varargout 함수들을이용하면이러한것이가능 M-파일 blockcomp.m을이용하여행렬에해당하는다음과같 은 블록컴패니언행렬을형성한다고가정 이를위하여다음과같은표준적인함수의정의를이용 function C = blockcomp(a1,a2,a3,a4,a5) 그러나위에서 m은 5로제한되어있으며 m이 1과 5 사이의값일때에는프로그램이복잡해짐 M-파일 blockcomp.m에보인바와같이 varargin을사용
% blockcomp.m: Block companion 행렬 function C = blockcomp(varargin) varargin m = nargin; n = length(varargin{1}); C = diag(ones(n*(m-1),1),-n); for j=1:m Aj = varargin{j}; C(1:n,(j-1)*n+1:j*n) = -Aj; end varargin 이입력인수목록으로지정되면공급된입력인수들은 varargin 라는이름의셀배열에복사 셀배열의원소들은중괄호를사용 >> X = ones(2); C = blockcomp(x, 2*X, 3*X) varargin = [2x2 double] [2x2 double] [2x2 double] C = -1-1 -2-2 -3-3 -1-1 -2-2 -3-3 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0
앞에서 varargin은 1 x 3 셀배열로서그원소들은 blockcomp에대한인수로제공된 2 x 2 행렬들이며 varargin{j} 은 j 번째입력행렬임 한편 nargout(number of argument of Output) 을이용하여얼마나많은출력인수들이요구되는가를결정한다음에요구되는출력을포함하는 varargout 셀배열을생성 M-파일 vecmom.m을작성하여 [m1,m2,...,mk] = vecmom(x) 는벡터 X의첫번째, 두번째,..., k번째모멘트가되도록함 ( 할당문의오른쪽에중괄호를사용하여 varargout을셀배열로만듬 )
% vecmom.m : 벡터의모멘트. function varargout = vecmom(x) % j 번째모멘트 = sum(x.^j)/length(x) for j=1:nargout varargout(j) = {sum(x.^j)/length(x)}; end M- 파일의수행결과 >> m1 = vecmom(1:4) m1 = 2.5000 >> [m1,m2,m3] = vecmom(1:4) m1 = 2.5000 m2 = 7.5000 m3 = 25
중첩함수 MATLAB에서는하나, 혹은그이상의함수들이다른함수안에완전히중첩되는것허용 중첩을정의하려면중첩된함수와주함수의맨끝에 end 문을두어야함 그렇게하지않으면함수들은부함수들이됨 중첩된함수들은들여쓰기하는것이알아보기에좋음 중첩함수는 MATLAB 7에서처음도입 두가지중요한성질 : 중첩함수는그것이중첩되어있는모든함수들의작업공간에접근이가능하다. 중첩함수에대한함수핸들은중첩함수에의접근에필요한정보와중첩함수를포함하는모든함수들의계산에필요한임의의변수값들에대한정보를저장한다. M-파일 nestfun.m에서는중첩함수 ratf에대한함수핸들이별개의함수 M-파일 appdt로전달됨 주함수 M-파일 nestfun.m의변수 a, b, c 및 d들은중첩함수 ratf 내에서접근이가능 값은 appdt로전달되는함수핸들내에포함
% appdt.m: 미분에대한유한차분근사. function y = appdt(f,x,h) % h: 차분파라미터 if nargin < 3 h = sqrt(eps); end y = (f(x+h) - f(x))/h; % nestfun.m : 중첩함수 (nested function) 의예시. function nestfun(x) a = 1; b = 2; c = 1; d = -1; appdt(@ratf,x) function r = ratf(x) r = (a+b*x)/(c+d*x); end end M- 파일의수행결과 >> nestfun(7) ans = 0.0833 >> nestfun(2) ans = 3.0000
비공개함수 (Private function) 통상적으로 MATLAB을설치하면사용자경로는수많은 M-파일들을포함하게되는데이들모두는 M-파일의이름만을입력하면바로사용가능 M-파일들에이렇게쉽게접근할수있는것이잇점이기도하지만함수이름들이혼란스러워지고서로충돌하거나중복될수있음 ( 비공개함수 (private function) 를이용하여방지 ) private라는이름의디렉토리에내장된함수들은상위디렉토리의함수들로부터만접근이가능하므로다른디렉토리의함수들은이들과동일한이름사용가능 MATLAB이함수를탐색할때에는먼저부함수들을탐색한다음에비공개함수들을탐색하고이어서현재의디렉토리와경로를탐색 비공개함수가공개함수와동일한이름을갖는다면비공개함수가제일먼저발견 비공개함수들은 gallery 함수에서잘이용되고있는데이함수는 matlab\elmat 디렉토리에위치하며시험용행렬들을모아두고있음 gallery에서호출되는 50개정도의행렬생성함수들은 matlab\elmat\private에위치하며기존함수와충돌하거나중복될염려가없이그이름들을선택가능 비공개디렉토리들은경로상에올려두지않아야함
되부름함수 (Recursive function) 함수들은자체내에서스스로를호출가능 M- 파일 makekoch.m 은 Koch 곡선을생성 % makekoch.m: Koch 곡선을생성 clear all level = 4; edges = 7; for k = 1:edges pl = [cos(2*k*pi/edges); sin(2*k*pi/edg es)]; pr = [cos(2*(k+1)*pi/edges); sin(2*(k+1 )*pi/edges)]; kochcurv(pl,pr,level); end axis('equal') title('koch snowflake','fontsize',14,'fon tangle','italic') hold off 이파일에서는아래와같은함수 M- 파일 kochcurv.m 을호출하고있는데함수 kochcurv 는 자기자신을반복호출함으로써 Koch 곡선을생성
% kochcurv.m: Koch 곡선. function kochcurv(pl,pr,level) if level == 0 plot([pl(1),pr(1)],[pl(2),pr(2)]); hold on else A = (sqrt(3)/6)*[0 1; -1 0]; pmidl = (2*pl + pr)/3; kochcurv(pl,pmidl,level-1) ptop = (pl + pr)/2 + A*(pl-pr); kochcurv(pmidl,ptop,level-1) pmidr = (pl + 2*pr)/3; kochcurv(ptop,pmidr,level-1) kochcurv(pmidr,pr,level-1) end Koch snowflake 0.8 0.6 0.4 0.2 0-0.2-0.4-0.6-0.8-1 -0.5 0 0.5 1 함수 kochcurv 로부터얻은 Koch 곡선 :
함수 kochcurv는세개의입력인수들을갖음 처음두개의인수 pl과 pr은현재선분의 (x,y) 좌표이며세번째인수 level은요구되는되부름단계 level=0이면하나의선분이그려지며그이외의경우에는 kochcurv는 level을하나줄이고네개의보다짧은선분들을정의하는끝점들을이용하여스스로를네번호출
MATLAB 내장수학함수 MATLAB은많은내장함수들을지님 sqrt, cos, sin, tan, log, exp, 그리고 atan들은물론 gamma, erf, 그리고 besselj와같은보다전문적인수학적함수들이포함. ( 함수 log는자연로그로서대개 ln" 으로호칭 ) MATLAB에내장되어있는수학함수들을보인것 삼각함수들은인수로서라디안을취하며 *d" 버전들은인수로서도 (degree) 를취함 특별한것들로서 expm1과 log1p가있는데이들은각각에대하여직접적인계산에영향을미치는생략을피하면서과를정확하게계산 MATLAB 내장수학함수 ( fun*" 는하나이상의함수이름이 fun" 으로시작됨을의미 ): 구분삼각함수역삼각함수하이퍼볼릭역하이퍼볼릭지수함수반올림복소수나머지, 부호수학함수수이론좌표변환 내장함수 cos, sin, tan, csc, sec, cot,cosd, sind, tand, cscd, secd, cotd acos, asin, atan, atan2, asec, acsc, acot, acosd, asind, atand, asecd, acscd, acotd cosh, sinh, tanh, sech, csch, coth acosh, asinh, atanh, asech, acsch, acoth log, log2, log10, log1p, exp, expm1, pow2, nextpow2, nthroot ceil, fix, floor, round abs, angle, conj, imag, real mod, rem, sign airy, bessel*, beta*, ellipj, ellipke, erf*, expint, gamma*, legendre, psi factor, gcd, isprime, lcm, primes, nchoos다, perms, rat, rats cart2sph, cart2pol, pol2cart, sph2cart
Gamma 함수 Gamma 함수 Gamma 함수는 는 ( ) 을만족 n 의 gamma 함수는함수 gamma 에의하여얻을수있음 >> gamma(6) ans = 120 >> y = gamma(-1) y = Inf >> y = gamma(-1.2) y = 4.8510 >> y = gamma(-2.2) y = -2.2050 와같이정의 와같은재귀적규칙을따르며 n 이양의정수라면
x 가음수일때의의값을의범위에서그래프 >> x = -5:0.01:0; >> plot(x,gamma(x)), xlabel('x'), ylabel('gamma(x)'), grid on >> axis([-5 0-40 100]) 100 80 60 Gamma(x) 40 20 0-20 -40-5 -4.5-4 -3.5-3 -2.5-2 -1.5-1 -0.5 0 x 음수에대한 Gamma 함수의그래프 :
불완전 Gamma 함수는아래와같이정의 gammainc 함수에의하여계산 >> x = 0.2; n = 0.3; >> y = x^n y = 0.6170 >> z = gammainc(x,n) z = 0.6575 >> x = 0.002; n = 0.003; y = x^n y = 0.9815 >> z = gammainc(x,n) z = 0.9832
Bessel 함수 Bessel 미분방정식은 의형태를가지며이의해는 로주어짐 위에서과는경계조건에의하여결정되는상수들이며은제 1 종 Bessel 함 수, 그리고 은제 2 종 Bessel 함수제 1 종 Bessel 함수는 와같이정의되며 Gamma 함수를포함 제 1 종 Bessel 함수는 MATLAB 의 besselj 함수로계산할수있으며제 2 종 Bessel 함수는 bessely(n,x) 로부터계산가능
범위에서의그래프를작성 >> x = [0:0.1:50]; >> y = besselj(1,x); >> plot(x,y), xlabel('x'), ylabel('besselj(1,x)') >> axis([0 30-0.4 0.6]) 0.6 0.5 0.4 0.3 BesselJ(1,x) 0.2 0.1 0-0.1-0.2-0.3-0.4 0 5 10 15 20 25 30 x 음수에대한 Gamma 함수의그래프 :
범위에서의그래프 >> x = [0:0.1:20]; >> u = besselj(0,x); v = besselj(1,x); w = besselj(2,x); >> plot(x,u,x,v,':',x,w,'.-'), xlabel('x'), yl abel('besselj(n,x)') >> grid on, legend('bessel0(x)','bessel1 (x)','bessel2(x)') 1 bessel0(x) bessel1(x) bessel2(x) 0.5 BesselJ(n,x) 0-0.5 0 2 4 6 8 10 12 14 16 18 20 x 의그래프
Beta 함수 Beta 함수는아래와같이정의됨 MATLAB 의 beta 함수를이용하여 Beta 함수를계산가능 B(1,n) 을계산 >> x = [1:10]'; >> y = beta(1,x); >> A = [x,y] A = 1.0000 1.0000 2.0000 0.5000 3.0000 0.3333 4.0000 0.2500 5.0000 0.2000 6.0000 0.1667 7.0000 0.1429 8.0000 0.1250 9.0000 0.1111 10.0000 0.1000
지수적분 지수적분은아래와같이정의되는적분으로서 x 의함수 지수적분은 MATLAB 함수 expint 에의하여계산 >> x = [0.1:0.2:2]'; >> y = expint(x); >> A = [x y] A = 0.1000 1.8229 0.3000 0.9057 0.5000 0.5598 0.7000 0.3738 0.9000 0.2602 1.1000 0.1860 1.3000 0.1355 1.5000 0.1000 1.7000 0.0747 1.9000 0.0562
Riemann Zeta 함수 Riemann Zeta 함수는수열 에의하여정의 MATLAB 에서 Riemann Zeta 함수를구하려면 w = mfun('zeta',z) 와같이입력 는 >> x = mfun('zeta',2) x = 1.6449
의범위에서 Zeta 함수의그래프 >> x = linspace(0,10); >> y = mfun('zeta',x); >> plot(x,y), xlabel('x'), title(' Zeta(x)'), axis([0 10-10 10] ) 10 Zeta(x) 8 6 4 2 0-2 -4-6 -8-10 0 1 2 3 4 5 6 7 8 9 10 x Zeta(x) 의그래프
Legendre 함수 Legendre 미분방정식은 로주어지는방정식으로서이의해는 로주어짐 여기에서는 1종 Legendre 다항식, 는 2종 Legendre 다항식으로불리는다항식들이다. 는 MATLAB 함수 legendre에의하여계산 의범위에서 n=1일때 m=0이나 m=1에대한은 >> x = -1:0.5:1; >> P = legendre(1,x) P = -1.0000-0.5000 0 0.5000 1.0000 0-0.8660-1.0000-0.8660 0
P 의첫번째행은 m=0, 두번째행은 m=1 에대한값 >> x = linspace(-1,1); >> p1 = legendre(1,x); >> plot(x,p1), xlabel('x'), ylabel('p1') 1 0.8 0.6 0.4 0.2 p1 0-0.2-0.4-0.6-0.8-1 -1-0.8-0.6-0.4-0.2 0 0.2 0.4 0.6 0.8 1 x 와의그래프
Airy 함수 Airy 함수는미분방정식 수있음 에대한해로서이함수는다음과같이나타낼 MATLAB 함수 airy 를이용하면 Airy 함수값을계산가능 >> x = linspace(-10,5); >> y = airy(x); >> plot(x,y), xlabel('x'), ylabel('ai(x)'), grid on Warning: Imaginary parts of complex X and/or Y arguments ignored. 0.6 0.4 0.2 0 Ai(x) -0.2-0.4-0.6-0.8-10 -5 0 5 x Airy 함수의그래프