반응형
Recent Posts
Recent Comments
Link
관리 메뉴

공머씨의 블로그

내가 공부한 옥타브2 18. 사용자정의함수 만들어서 사용하기 본문

내가 공부한 옥타브(매틀랩)/내가 공부한 옥타브 시리즈2 (공업수학1)

내가 공부한 옥타브2 18. 사용자정의함수 만들어서 사용하기

공머씨 2020. 4. 18. 10:22
반응형

이번에는 매트랩에서 사용자 정의 함수를 만들어서 사용하는 방법에 대해 공부해보겠습니다.

지금까지 우리가 사용한 함수는 내장 함수 (Bulite-in function)입니다.

옥타브 , 매트랩 프로그램 안에 미리 저장되어있던 함수들입니다.

23. 다음 예제는 사용자 정의 함수를 정의하고 호출해서 사용하는 방법을 설명하는 코드입니다.

 

매트랩, 옥타브에서 사용자 정의 함수는 반드시  fuction이라는 키워드로 시작되고

myfunc라는 함수 이름은 마음대로 정하시면 됩니다.

괄호 안에 들어있는 것은 함수의 인자입니다.

y=x^2;  은 리턴 값을 저장하는 저장하는 변수입니다.

x라는 인자를 받으면 제곱하는 기능의 함수입니다.

 

 

이런 함수를 만든 다음 파일 이름으로 저장합니다.

항상 함수 이름과 m파일의 이름이 같아야 합니다.

저장한 뒤 에디터를 종료하면 다음부터 command window에 바로 호출을 하여 사용할 수 있습니다.

 

 

 

예를 들어 명령 창에 아래와 같은 함수를 입력하면 3이 인자로서 저장이 됩니다.

그러면 위의 함수의 리턴 값으로는 9가 나오게 됩니다.


함수가 정의되어있는  m파일에서는 다음과 같은 형태로 작성해야 합니다.

 

function  아무문자=함수이름(인자,인자...)

             아무문자= 함수내용

endfunction

 

f가 아니라 a이어도 y이어도 실행이됩니다.

실수로 인자를 작성하지않으면 다음과 같은 오류메세지가 출력됩니다.

보통 함수가 저장되어있는m파일의 이름을 함수이름과 같도록 저장합니다.

그리고 함수를 호출하는 부분에서는 다음과 같이 호출해야합니다.

함수를 그릴때 좌표를 함수이름(인자)로 작성해주어야 합니다.

실수로 y라고 작성하는 경우가 간혹있는데 다음과 같은 오류메세지가 나옵니다.

 

만약 y라고 부르고 싶다면 함수를 불러서 plot을 그리는 파일에

에디터 두번째 줄과 같이 y를 정의해주어야 합니다.

 

참고로 myfunc(x)는 다음과 같이 작성 하였습니다.

 

 


 

다음과 같은 방식으로 변수에 숫자를 저장한 뒤

인자에 변수를 넣어주는 방법도 있습니다.

 

전달하는 인자에 벡터 (행 벡터)를 전달하려면????

위의 코드를  실행시켜 보겠습니다.

위 사진과 같이 error가 발생합니다.

벡터의 제곱을 계산하라는 명령이 되는데 

사이즈가 맞지 않기 때문에 오류가 생기는 것입니다.

 

벡터 t는 사이즈가 1⨉11입니다.

행렬 t끼리 제곱한다는 것은 1⨉11 행렬과 1⨉11 행렬을 곱하는 것과 같습니다.

따라서 앞행렬의 열과 뒤 행렬의 행이 다르기 때문에 행렬 곱셈이 안됩니다.

 

행렬에서 각원소끼리 제곱이 되는 어레이 연산을 사용해주어야 합니다.

옥타브에서 원소끼리 곱할 때는 반드시 요소별 연산자(Array 연산자) .*  를 사용함을 떠올리면 됩니다.

 

>> Editor파일에서 벡터를 인자로 넣어도 오류가 나지 않도록 수정해봅시다.

 

 

 

그렇게 처음의 myfunc라는 함수를 수정한 뒤에는  인자가 스칼라일 때도, 벡터일 때도 계산이 가능한 함수가 됩니다.

 

 

아래와 같이 return 값에서 인자에 단위별 요소 연산자를 사용해서 제곱해주면 됩니다.

 

 

 

3번에서는 다른 스크립트 파일을 사용하여 

새로운 파일을 열어서 

ex14a라는 이름으로 m파일을 저장합니다.

그 파일에 다음 3줄의 코드를 입력합니다.

t=[-2:0.1:2];
y=myfunc(t);
plot(t,y)

 

myfunc를 이미 저장해놓았기 때문에, t의 제곱을 계산하여 되돌아오게 됩니다.

plot y라고 하면 t를 x축  y를 y축으로 하여 그래프가 그려지게 됩니다.

 

그냥 파일 하나에 바로 입력해도 실행됩니다.

예를 들어 

y=t.^2 한 다음

plot() 해도 당연히 그래프를 그릴 수 있습니다.

하지만 굳이 두 개의 함수를 저장해놓고 호출하여 그래프를 그린 이유는 함수를 만들고 호출해서 사용하는 연습을 하기 위함입니다.

 

이 연습이 잘 되면 14장은 잘 끝났습니다.

계속 반복해보도록 하겠습니다.

 

예제 14b 함수 만들기 

 

 구간별로 정의된 함수입니다. (정의역에 따라 함숫값이 결정되므로 if를 사용해서 구별해주면 됩니다.)

 

(1) t가 주어지면 무조건 그 t에 대해서 함숫값을 계산하는 매트랩 함수를 myf라고 저장하면

사용자 정의 함수가 만들어집니다.

 

(2) 새로운 에디터파일을 열어서 (2) 번 설명과 같은 함수를 만듭니다.

하나의 좌표에 두개의 그래프를 겹쳐서 작성합니다. (hold on, hold off사용)

한 파일안에서 함수를 사용하지 않아도 계산이 가능하지만 , 함수 연습을 위한 문제이므로 반드시 myf를 호출해서 계산하도록 합니다.

하나의 좌표에 두개의 그래프를  plot 하므로 구분이 가능하도록 검은색 실선, 빨간색 점선으로 만듭니다. (내공 옥 7.2D그래프 참조)

gtext() 내장 함수를 사용해서 각각 그래프 옆에  f(t) f(2t)를 표기합니다.

※ f(2t)는 f(t)의 그래프를 수평축 방향으로 2/1축소한 그래프.

 

답은 다음과 같습니다.

 

정의역에 숫자를 하나씩 집어넣으면 (스칼라) 오류가 발생하지않지만

벡터를 집어넣으면 계산을 수행하지 않습니다.

조건문을 살펴보면,

t가 -1보다 클 때, t가 0보다 크고 1보다 작을 때  조건을 붙입니다.

t가 스칼라일 때는 조건을 잘 확인할 수 있지만,

t가 벡터라면 (t값이 하나가 아닌 여러 개가 나옵니다.) 조건을 check가 어렵기 때문에 잘 계산이 안됩니다. 위와 같이 하면 안 됩니다.

 

 

 

아래와 같이 수정하면 되겠습니다.

t가 숫자 여러 개를 동시에 갖는 array이기 때문에 배열 전체에 있는 숫자 각각에 대해서 아래와 같은 조건을 체크해서 값을 계산하는 방식입니다. (숫자 각각의 조건을 체크하기 위해 for문을 이용했습니다)

and 보다는 부등호를 먼저 계산하기 때문에 괄호가 없어도 됩니다.

우선순위가 관계 연산자 다음이 논리 연산자 이기 때문입니다.

(&앞뒤의 조건 자체에 괄호가 없어도 됩니다. )

%함수파일

function y=myf(t)
for k=1:length(t)
  if (-1<=t(k))&(t(k)<0)
    y(k)=t(k)+1;
  elseif(0<=t(k))&(t(k)<1)
    y(k)=-t(k)+1;
  else
    y(k)=0;
  endif
 endfor
endfunction
%함수th를 사용하는 파일
t=[-2:.1:2];
y1=myf(t);
y2=myf(2*t);

plot(t,y1,'r')
hold on

plot(t,y2,'k')

hold off

 

 

 

 

 

위보다 더 좋은 방법도 있습니다.

위와  같이 MATLAB스타일의 코드로 작성하면 한  줄로 작성할 수 있습니다.

 

&앞에 있는 항을 보면

t가 조건을 만족하면 1이 됩니다. 그때는 t+1을곱합니다.

조건을 만족하지 않으면 0이 된다. 아무것 곱하지 말라는 뜻입니다.

 

두 번째 항을 보면 이 조건을 만족할 때 -t+1을 곱하라는 것이므로

만족하지 않으면 곱해지지 않습니다.

 

앞으로 매트랩에서 구간별로 정의된 함수를 만들려면  위와 같은 한 줄로 계산하면 됩니다.

 

잘되면 저장해놓고 에디터 파일을 열어서 

또 다른 프로그램을 만들어보겠습니다.

이전에 만들었던 함수를 (myf) 호출해서 함숫값을 계산하고 그래프를 그리는 프로그램입니다.

 

이 프로그램에선 아래와 같은 힌트를 보고 코딩하시면 되겠습니다.

 

 

hold on앞의 그래프가 지워지지 않고 그대로 남아있도록 하는 명령입니다. 

= 원래 그래프가 그려져 있는 채로, 새로운 그래프를 겹쳐 그릴 때 hold on을 사용합니다.

  1. 명령어 hold on는 plot과 같은 그래픽 명령어 실행 후에 실행되어야 합니다.

  2. 명령어 hold on는 명령어 hold off가 실행되기 전까지 모든 그래픽 작업이 현재 열린 창에 실행되도록 합니다

어디에 입력하든 상관은 없습니다. hold on 또는 hold off가 실행되는 시점 기준으로 이전 그래프들을 유지할 거냐 말 거냐가 결정됩니다.

hold off 한다고 바로 그래프가 지워지는 게 아닙니다. 무언가를 그리면 없어집니다.

 

아래와 같이 hold off 한 다음

새로운 함수를 만들면 

처음 만든 그래프가 지워졌다가  hold off를 빠져나가면서 새로운 입력한 그래프가 자동적으로 그려집니다.

hold 앞에 다음과 같은 코드를 입력해보고 실행해보시기를 바랍니다.

%ex14b문제 해답
%myf m파일도 필요함

t=[-2:0.1:2]
y1=myf(t)
y2=myf(2*t) %함수f(2t)를 계산 함
plot(t,y1,'k-') % k는 검정색, -은 실선을 의미합니다.
gtext('f(t)','FontSize',20)
hold on %이 그래프를 다음줄의 그래프와 겹쳐서 그릴 수 있도록 그대로 유지
plot(t,y2,'r:') %
gtext('f(2t)','FontSize',20)
xlabel('t')
ylabel('y')
title('ex14b')
hold off

 

 

%ex14b에 쓰이는 함수
%matlab스타일로 함수만들기
function ft=myft(t)
  ft=(t+2).*(-2<t&t<-1)+1.*(-1<=t&t<=1)+(-t+2).*(1<t&t<=2)+0.*(t<-2)+0.*(2<t)
  
endfunction

 

 

 

 

text() 함수: 좌표, 출력하고 싶은 텍스트를 입력

gtext() 함수 : 출력하고 싶은 텍스트를 입력하면 그림 창에 마우스 클 클릭한뒤 계속 프로그램이 진행된다는 특징이 있습니다.

y=sin(t)
plot(t,y)

 

 

 

예제 14c

이번에는 인자가 3개인 함수를 만들어봅니다. 작성한 뒤 적당한 이름을 저장합니다.

m값과 시그마 값을 바꾸어주면서 4개의 그래프를 그려야 하는데, 한 좌표축에 겹쳐 그립니다.

그래프 옆에 text를 찍을 때 직접 tex함수를 사용했습니다.

legend함수를 사용하면 자동으로 그래프를 구별해줍니다.

 

아래와 같은 힌트를 보고 코딩해보시면 됩니다.

 

 

 

첫 번째로 할 일은 함수가 저장된  함수 파일을 만듭니다. (함수 이름과 함수를 저장한 m파일의 이름은 같아야 함에 주의합니다.)

return 값은 y에 넣으라고 정의하고 있습니다.

 

두 번째 단계는

또 다른 에디터 파일을 열어서 함수를 호출하여 프로그램을 만듭니다

앞에서 저장해둔 함수를 호출하면 y 값이 저장이 됩니다.

2,3,4 번째 그래프도 겹쳐서 그려야 하므로 holdon 해줍니다.

마지막으로 legned () 함수를 사용합니다.

4개의 범례를 () 안에 인자로 입력해주면 

자동으로 앞에서 그린 그래프를 구별하여 범례를 표시합니다.

 

legend('이름', '이름')을 하시면 그린 순서대로(파란 줄, 빨간 줄) 이름이 표시됩니다.

>> legend('y=2*x', 'y=4.*x') 

출처: https://engi-agora.tistory.com/7 [Engineer-Agora]

 

전체 소스코드와 결과 화면입니다.

 

 

 

 

%스크립트 m파일 ex14.c
%gfunc 파일이 필요합니다.

x=[-6:0.001:6];
(x>-6) && (x<6);
m=0;sigma=1;
y=gfunc(x,m,sigma); %m=0,sigma=1 에 대한 함숫값계산
plot(x,y,'k-') %y그래프를 검은색 실선으로 그릴 것
hold on; %그래프를 그대로 유지한다.

m=0;sigma=2;      %다른 m,sigma 값에 대해 함숫값을 계산하고 , 그래프를 그린다.
y=gfunc(x,m,sigma);
plot(x,y,'r:')
hold on;

m=2;sigma=1;      %다른 m,sigma 값에 대해 함숫값을 계산하고 , 그래프를 그린다.
y=gfunc(x,m,sigma);
plot(x,y,'b-.')
hold on;

m=2;sigma=2;      %다른 m,sigma 값에 대해 함숫값을 계산하고 , 그래프를 그린다.
y=gfunc(x,m,sigma);
plot(x,y,'g--')

xlabel('x')
ylabel('y')
title('ex14c ')

legend('m=0,sigma=1','m=0,sigma=2','m=2,sigme=1','m=2,sigma=2');%범례표시
%ex14c에서 사용하는 사용자정의함수 입니다.
function y=gfunc(x,m,sigma)
  y=1/(sqrt(2*pi.*sigma^2)).*exp((-(x-m).^2)/(2*sigma.^2));
endfunction

 

 

 

 

 

 

예제 14d는 

14b와 유사합니다. 구간만 조금 달라졌습니다.

이미 우리가 앞에서 한 줄로 코딩하는 방법을 알았으므로 이를 응용해서 14d의 함수를 자기 마음대로 

f, g, h라는 함수를 프로그래밍해보라는 뜻입니다.

 

우리가 14b에서 이야기하였듯이 수평방향으로 2배 늘린 함수는 x대신 2x

즉, f(x) 대신 f(2x)를 넣으면 됩니다.

 

이번에는 어떤 힌트도 없습니다.

스스로 처음부터 끝까지 코딩해보시면 됩니다.

함수를 만들어서 사용하는 것은 매우 중요하므로 위의 예제 들을 열심히 연습해서 

매트랩에서 함수를 어떻게 정의하고 사용하는지 잘 알아두시길 바랍니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

전체코드입니다.

%함수 ex14d에 대한 코드입니다. 
%myfx파일과 함께사용합니다.

x=[-6:0.01:6];
plot(x,myfx(x),'k-')
gtext('f(x)')
hold on;

%g(x)그래프 입니다. 
plot(x,myfx(x/2),'r:')
gtext('g(x)=f(x/2)')
hold on;

%h(x)그래프 입니다. 
plot(x,2.*myfx(x-3),'b--')
gtext('h(x)=2f(x-3)')
hold on;

xlabel('x')
ylabel('y')
title('ex14d ')
legend('f(x)','g(x)','h(x)');

 

 

사용자 정의함수를 매트랩스타일로 만들었습니다.

%ex14d와 함께 사용하는 함수입니다.
function fx=myfx(x)
fx=(x+1).*(-1<x &x<=0)+1.*(0<x & x<=1)+((x-2).^2).*(1<x & x<=2)

 

 

결과화면 입니다.

 

 

 

 

 

반응형
Comments