2017년 7월 6일 목요일

옥타브/매트랩 - 2. 함수, 입출력, 제어구조, 행렬

octave_matlab__2

옥타브 / 매트랩


사용자 제어 입출력

input 함수

input 함수를 사용하여, 사용자가 데이터를 입력하는 프로그램을 만들 수 있다.
input 함수는 다양한 종류의 데이터를 받아들일 수 있다.
• 스칼라
In [1]:
x = input('Enter a value : ')
Enter a value :1
x =  1
• 행렬
숫자를 사각형 괄호 [  ] 안에 입력한다.
In [2]:
x = input('Enter a value : ')
Enter a value :[ 1 2 3 ]
x =

   1   2   3

• 문자열
문자열을 작은 따옴표 ' 로 묶는다.

input 함수의 두 번째 필드에 's' 를 쓰면, 작은 따옴표로 묶을 필요가 없다.
In [3]:
x = input('Enter a value : ')
Enter a value :'문자열을 따옴표로 묶는다'
x = 문자열을 따옴표로 묶는다
In [4]:
x = input('Enter a value : ', 's' )
Enter a value :그냥 문자열만
x = 그냥 문자열만

disp 함수

간편한 출력의 용도에 쓰인다.
disp 함수로 출력하는 경우, 행렬의 이름이 표시되지 않는다.
In [5]:
x = [ 1 2 3 ] ;
x

disp(x)
x =

   1   2   3

   1   2   3
문자열을 출력할 수 있다.
In [6]:
disp(' 문자열 ')
 문자열 
작은 따옴표를 출력하려면 있으면, ' ' 와 같이 두 번 쓴다.
In [7]:
disp('It''s me.')
It's me.

fprintf 함수

사용자가 출력 형식을 지정하여 출력한다.
형식 지정자
형식 지정자 표시 형식
%f 고정소수점 형식
%e 지수 형식
%g %f 와 %e 중에 짧은 형식
%c 문자
%s 문자열
In [8]:
fprintf('원주율의 값 = %10.6f \n', pi )
원주율의 값 =   3.141593 
%10.6f 는 고정소수점 형식으로 10개의 칸에 소숫점 이하 6자리까지 출력을 지정한다.
\n 은 줄바꾸기 (new line) 기호이다. 쥬피터 노트북에서 \n 을 생략하면 같은 결과가 두 번 출력된다.
% 기호를 출력하려면, %% 와 같이 두 번 쓴다.
In [9]:
fprintf('A+ 는 10%% 이상 줄 수 없습니다. \n')
A+ 는 10% 이상 줄 수 없습니다. 
파일로 출력하기
In [10]:
out = fopen('result.txt','wt');     % out 은 사용자가 지정하는 출력 객체
fprintf( out, '원주율은 %8.6f 입니다. \n', pi );
fclose( out );
도스 명령어 type filename 으로 파일의 내용을 볼 수 있다.
In [11]:
type result.txt
원주율은 3.141593 입니다. 

사용자 정의 함수

function 출력변수 = 함수이름 ( 매개변수 )
$\quad$ ... 함수의 내용 ...
end
※ (옥타브) end 대신에 endfunction 이라고 쓸 수 있다.
In [12]:
function output = square(x)
output = x .^ 2 ;
end

square(1:5)
ans =

    1    4    9   16   25

M 파일 만들기 ( 확장자 .m )

  • 사용자가 함수를 M 파일로 만들어 저장해두고 언제든 이용할 수 있다.
  • 함수에서 사용되는 모든 변수는 지역변수이다.
  • 함수의 이름과, 함수를 저장하는 M 파일의 이름은 반드시 같아야 한다.
현재의 디렉터리에 있는 M 파일들의 목록을 보려면
In [13]:
dir *.m
testfunc.m
M 파일의 내용을 보려면
In [14]:
type testfunc.m
testfunc.m is the user-defined function defined from: D:\ch\Chang\Program\Python\Ÿ\testfunc.m

function testfunc( x )
  disp( x )
end
M 파일의 함수를 불러서 실행해 본다.
In [15]:
testfunc( 'Hello' )
Hello

함수의 입력이 여러 개인 경우

In [16]:
function output = multi( x, y )
output = x .* y ;
end

multi(3,7)

output
ans =  21
error: 'output' undefined near line 1 column 1
※ 오류: output 은 함수의 지역변수이므로, 함수 바깥에서는 유효하지 않다.

함수의 출력이 여러 개인 경우

In [17]:
function [ area, circum ] = circle( radius )
area = pi * radius ^2 ;
circum = 2 * pi * radius ;
end

[ A, S ] = circle(10)
A =  314.16
S =  62.832

함수가 다른 함수를 호출하는 경우

In [18]:
function [result1, result2] = func( x, y )
result1 = add(x,y);
result2 = subtract(x,y);
end

function result = add( x, y )
result = x + y ;
end

function result = subtract( x, y )
result = x - y ;
end

[ r1, r2 ] = func( 6, 2 )
r1 =  8
r2 =  4

관계 연산자

기호 $\quad$ 의미
< … 보다 작다
<= … 보다 작거나 같다
> … 보다 크다
>= … 보다 크거나 같다
== … 와 같다
~= … 와 같지 않다
관계 연산의 결과가 참이면 1, 거짓이면 0 이다. 즉, 연산의 결과가 숫자로 표시된다.
In [19]:
x = 1 ;
y = 2 ;
x < y
ans =  1

논리 연산자

기호 $\quad$ 의미
& 그리고 (and)
또는 (or)
~ 부정 (not)
In [20]:
x = [ 1 2 3 ] ;
y = [ 1 3 5 ] ;
z = [ 2 4 6 ] ;
x<y & x<z
ans =

   0   1   1

if 조건문

if $\,\,$ 조건문
$\quad$... '참'이면 실행할 문장 ...
end
In [21]:
x = 1 ;

if x > 0 
  disp('It is positive')
end

if x < 0
  disp('It is negative')
end
It is positive
if $\,\,$ 조건문
$\quad$... '참'이면 실행할 문장 ...
else
$\quad$... '거짓'이면 실행할 문장 ...
end
In [22]:
x = -1 ;

if x > 0 
  disp('It is positive')
else
  disp('It is negative')
end
It is negative
if $\,\,$ 조건문 1
$\quad$... 조건문 1 이 '참'이면 실행 ...
elseif $\,\,$ 조건문 2
$\quad$... (조건문 1 이 '거짓'이고) 조건문 2 가 '참'이면 실행 ...
elseif $\,\,$ 조건문 3
$\quad$... (조건문 1, 2 가 '거짓'이고) 조건문 3 이 '참'이면 실행 ...
else
$\quad$... 조건문들이 모두 '거짓'이면 실행 ...
end
In [23]:
x = input('정수를 입력하시오 :');

if mod(x,3) == 0 
  disp('3 으로 나눈 나머지가 0')
elseif mod(x,3) == 1
  disp('3 으로 나눈 나머지가 1')
else
  disp('3 으로 나눈 나머지가 2')
end
정수를 입력하시오 :5
3 으로 나눈 나머지가 2
※ if 조건문에 행렬이 사용되는 경우
행렬의 모든 원소에 대하여 '참'일 경우에만, 조건문이 '참'이 된다
In [24]:
x = [ 8 9 10 ] ;

disp( x < 10 )

if x < 10
  disp('10 보다 작다')
end

if x > 0 
  disp('It is positive')
end
   1   1   0
It is positive
이런 이유로, 가능하면 조건문에서는 행렬을 사용하지 않는 것이 좋다.

반복문

for 루프

for $\,$ 변수 = [행렬]
$\quad$ ... 실행할 문장 ...
end
행렬의 각 원소에 대해 루프(loop)가 한 번씩 실행된다.
In [25]:
for k = [ 1, 3, 5 ]
  k
end
k =  1
k =  3
k =  5
1 부터 10 까지의 합을 구해본다.
In [26]:
sumk = 0 ;

for k = 1:10
  sumk = sumk + k ;
end

disp( sumk )
 55

while 루프

while $\,$ 조건문
$\quad$ ... 실행할 문장 ...
end
while 루프는 조건이 만족하는 동안에 루프를 계속 반복한다.
1 부터 10 까지의 합을 구해본다.
In [27]:
sumk = 0 ;
k = 1 ;

while k <= 10
  sumk = sumk + k ;
  k = k + 1 ;
end

disp( sumk )
 55
break 문을 만나면 루프의 실행을 중단하고, 루프를 완전히 벗어난다.
In [28]:
while 1
  x = input('Enter a value (''q'' to quit):');
  disp(x)
  
  if x == 'q' 
    break
  end
  
end
Enter a value ('q' to quit):1
 1
Enter a value ('q' to quit):2
 2
Enter a value ('q' to quit):'q'
q
continue 문을 만나면 루프 실행을 중단하고, 루프의 시작 부분으로 이동하여 실행을 계속한다.
In [29]:
while 1
  x = input('Enter a positive value (''q'' to quit):');
  disp(x)
  
  if x <= 0
    disp('I said positive !')
    continue
  end
  
  if x == 'q' 
    break
  end
  
end
Enter a positive value ('q' to quit):0
0
I said positive !
Enter a positive value ('q' to quit):1
 1
Enter a positive value ('q' to quit):'q'
q

중첩 루프

루프 안에 루프가 있는 구조
입력한 행렬의 최대값을 갖는 원소를 찾아본다.
In [30]:
x = input('행렬을 입력하시오 :')

[ nrow, ncol ] = size( x ) ;
max = - realmax ;

for row = 1 : nrow
  for col = 1 : ncol
  
    if x(row,col) > max
      max = x(row,col) ;
    end
    
  end
end

printf('최대 원소값 = %12.5f \n', max ) ;
행렬을 입력하시오 :[ 1 2 5; 8 7 6 ]
x =

   1   2   5
   8   7   6

최대 원소값 =      8.00000 

배열 연산

배열 연산자 (같은 위치에 있는 원소들 사이의 계산)
A .* B   A와 B의 같은 위치에 있는 원소들 사이의 곱셈
A ./ B   A와 B의 같은 위치에 있는 원소들 사이의 나눗셈
A .^ B   A와 B의 같은 위치에 있는 원소들 사이의 거듭제곱

행렬 연산

  • 행렬 전치 (Transpose)
  • 점곱 (Dot product)
  • 가위곱 (Cross product)
  • 행렬 곱셈 (Multiplication)
  • 행렬 거듭제곱
  • 행렬식 (Determinant)
  • 역행렬 (Inverse)
  • 행렬 왼쪽나눗셈 (Left Division) : 매트랩의 가우스 소거법

행렬 전치 (Transpose)

행렬의 행과 열을 서로 바꾸는 연산을 전치 연산이라한다.
전치 연산자는 작은 따옴표 ' 이다.
In [31]:
a = [ 1 2 3; 4 5 6 ]
a =

   1   2   3
   4   5   6

In [32]:
a'
ans =

   1   4
   2   5
   3   6

복소수 행렬의 전치

In [33]:
x = [ -1:-1:-3 ] 
y = sqrt(x)
x =

  -1  -2  -3

y =

   0.0000 + 1.0000i   0.0000 + 1.4142i   0.0000 + 1.7321i

복소수 행렬에 전치 연산을 하면, 켤레복소수 값이 반환된다.
In [34]:
y'
ans =

   0.0000 - 1.0000i
   0.0000 - 1.4142i
   0.0000 - 1.7321i

점곱 (Dot product)

벡터의 같은 위치에 있는 원소끼리 서로 곱한 결과를 모두 더하는 연산.
내적 (inner product)라고도 한다.
$$ \sum _{ i=1 }^{ N } A _i \, B _i = \left| {\mathbf A} \right| \, \left| {\mathbf B} \right| \, \cos \theta $$
점곱의 결과는 스칼라가 되므로, 점곱을 스칼라곱(scalar product)이라고도 한다.
점곱을 구하는 명령
  • sum( A .* B )
  • dot( A, B )
In [35]:
A = [ 1 2 3 ] 
B = [ 4 5 6 ]
A .* B
A =

   1   2   3

B =

   4   5   6

ans =

    4   10   18

In [36]:
sum( A .* B )
dot( A, B )
ans =  32
ans =  32
※ 옥타브/매트랩에서 sum 은 예약어이므로, 변수 이름으로 혼용하면 오류가 발생할 수 있다.

가위곱 (Cross product)

벡터의 가위곱 결과는 벡터가 된다.
$$ \mathbf A \times \mathbf B = ( A_y B_z - A_z B_y ) \, \mathbf i + ( A_z B_x - A_x B_z ) \, \mathbf j + ( A_x B_y - A_y B_x ) \, \mathbf k $$
가위곱은 벡터곱 (vector product), 외적 (outer product)이라고도 한다.
기하학적으로, 가위곱은 두 벡터가 만드는 평면과 직각을 이룬다. 이러한 성질을 직교성 (orthogonality) 이라고 한다.
가위곱을 계산하는 명령
  • cross(A,B)
In [37]:
A = [ 1 2 3 ] ;
B = [ 4 5 6 ] ;
C = cross( A, B )
C =

  -3   6  -3

가위곱이 두 벡터와 직각을 이루는지 확인한다.
In [38]:
dot( C, A )
dot( C, B )
ans = 0
ans = 0

행렬 곱셈 (Multiplication)

곱셈이 정의되기 위해서는, 행렬 A의 열의 갯수는 행렬 B의 행의 갯수와 같아야 한다.
$$ c _{ij} = \sum _{ k=1 }^{ p } a _{ik} \, b _{kj} $$
$$ \mathbf C = \mathbf {A\,B} = \begin{pmatrix} a_{ 11 } & a_{ 12 } & \cdots & a_{ 1j } & \cdots & a_{ 1p } \\ a_{ 21 } & a_{ 22 } & \cdots & a_{ 2j } & \cdots & a_{ 2p } \\ \vdots & \vdots & & \vdots & & \vdots \\ a_{ i1 } & a_{ i2 } & \cdots & a_{ ij } & \cdots & a_{ ip } \\ \vdots & \vdots & & \vdots & & \vdots \\ a_{ m1 } & a_{ m2 } & \cdots & a_{ mj } & \cdots & a_{ mp } \end{pmatrix} \,\, \begin{pmatrix} b_{ 11 } & b_{ 12 } & \cdots & b_{ 1j } & \cdots & b_{ 1n } \\ b_{ 21 } & b_{ 22 } & \cdots & b_{ 2j } & \cdots & b_{ 2n } \\ \vdots & \vdots & & \vdots & & \vdots \\ b_{ i1 } & b_{ i2 } & \cdots & b_{ ij } & \cdots & b_{ in } \\ \vdots & \vdots & & \vdots & & \vdots \\ b_{ p1 } & b_{ p2 } & \cdots & b_{ pj } & \cdots & b_{ pn } \end{pmatrix} $$
In [39]:
A = [ 1 2 3; 4 5 6 ]
B = [ 10 20; 30 40; 50 60 ]
A * B
A =

   1   2   3
   4   5   6

B =

   10   20
   30   40
   50   60

ans =

   220   280
   490   640

행벡터 $*$ 열벡터 는 점곱 (내적)과 같다.
In [40]:
A = [ 1 2 3 ]
B = [ 3; 4; 5 ]
A * B
A =

   1   2   3

B =

   3
   4
   5

ans =  26
일반적으로, 두 행렬 A와 B의 행렬 곱셈은 교환법칙이 성립하지 않는다.
$$ \mathbf {A\,B} \, \neq \, \mathbf {B \, A} $$
하지만, 결합법칙은 성립한다.
$$ \left( {\mathbf A \, \mathbf B} \right ) \mathbf C \,=\, \mathbf A \left( { \mathbf B \mathbf C } \right ) $$

행렬 거듭제곱

같은 행렬을 여러 번 곱하는 것을 행렬의 거듭제곱이라고 한다.
  • $\text { A^2 = A * A }$
  • $\text { A^3 = A * A * A }$
어떤 행렬을 거듭제곱하려면, 그 행렬은 정방 행렬 (square matrix)이어야 한다.

행렬식 (Determinant)

행렬 A 가 $2 \times 2 $ 정방 행렬이면,
$$ \mathbf A \, =\, \begin{pmatrix} a_{ 11 } & a_{ 12 } \\ a_{ 21 } & a_{ 22 } \end{pmatrix} $$
행렬식은 다음과 같이 정의 된다.
$$ \det ( \mathbf A ) \,=\, \left | \mathbf A \right | \,=\, a_{11} a_{22} - a_{12} a_{21} $$
행렬식을 구하는 명령
  • det(A)
In [41]:
A = [ 1 2; 3 4 ]

det(A)
A =

   1   2
   3   4

ans = -2
행렬식의 값이 0 이면, 그 행렬은 역행렬이 존재하지 않는 특이행렬 (singular matrix)이다.
In [42]:
A = [ 1 1; 0 0 ]

det(A)
A =

   1   1
   0   0

ans = 0

역행렬 (Inverse)

행렬 A와 그 역행렬 A$^{-1}$ 을 곱하면, 그 결과는 단위 행렬이다.
$$ \mathbf {A A} ^{-1} = \mathbf A ^{-1} \mathbf A = \mathbf I $$
행렬 A의 역행렬을 계산하는 명령
  • inv(A)
또는
  • A^-1
In [43]:
A = [ 1 2; 3 4 ]

A^-1

A * A^-1
A =

   1   2
   3   4

ans =

  -2.00000   1.00000
   1.50000  -0.50000

ans =

   1.00000   0.00000
   0.00000   1.00000

행렬식의 값이 0 이면, 그 행렬은 역행렬이 존재하지 않는 특이행렬이다.
In [44]:
A = [ 1 2 3; 4 5 6; 7 8 9 ]

inv(A)

det(A)
A =

   1   2   3
   4   5   6
   7   8   9

ans =

  3.1522e+015  -6.3044e+015  3.1522e+015
  -6.3044e+015  1.2609e+016  -6.3044e+015
  3.1522e+015  -6.3044e+015  3.1522e+015

ans =  -9.5171e-016

선형 연립 방정식

다음 연립방정식을
$$x+2y+3z=7$$$$3x-2y+ z=5$$$$2x-3y+z=2$$
행렬의 곱셈으로 표현하면
$$ \begin{bmatrix} 1 & 2 & 3 \\ 3 & -2 & 1 \\ 2 & -3 & 1 \end{bmatrix} \, \begin{bmatrix} x \\ y \\ z \end{bmatrix} \,=\, \begin{bmatrix} 7 \\ 5 \\ 2 \end{bmatrix}$$
※ 연립 방정식의 벡터는 열벡터이다.
$$ \mathbf A = \begin{bmatrix} 1 & 2 & 3 \\ 3 & -2 & 1 \\ 2 & -3 & 1 \end{bmatrix} \qquad \mathbf X = \begin{bmatrix} x \\ y \\ z \end{bmatrix} \qquad \mathbf B = \begin{bmatrix} 7 \\ 5 \\ 2 \end{bmatrix} $$
$$ \mathbf {A X} \,=\, \mathbf B $$
양변에 역행렬 $\mathbf A ^{-1} $ 을 곱한다.
$$ \mathbf A ^{-1} \mathbf {A X} \,=\, \mathbf A ^{-1} \, \mathbf B $$
행렬의 곱셈에서는 결합법칙이 성립하므로
$$ \left ( \mathbf A ^{-1} \mathbf A \right) \mathbf X \,=\, \mathbf A ^{-1} \, \mathbf B $$
$\mathbf A ^{-1} \mathbf A = \mathbf I \, $ 이므로
$$ \mathbf I \, \mathbf X \,=\, \mathbf A ^{-1} \, \mathbf B $$
$$ \mathbf X \,=\, \mathbf A ^{-1} \, \mathbf B $$
※ 교환법칙은 성립하지 않는다. $\,\, \mathbf A ^{-1} \, \mathbf B \, \neq \, \mathbf B \, \mathbf A ^{-1} $

역행렬을 사용하여 해를 구하기

In [45]:
A = [1 2 3; 3 -2 1; 2 -3 1]
B = [7; 5; 2]
X = inv(A) * B
A =

   1   2   3
   3  -2   1
   2  -3   1

B =

   7
   5
   2

X =

   2
   1
   1

행렬 왼쪽나눗셈 (Left Division)

왼쪽나눗셈은 가우스 소거법(Gaussian elimination)을 사용하는 것으로서, 계산이 더 효율적이다.
$$ \mathbf X \,=\, \mathbf A ^{-1} \, \mathbf B $$
왼쪽나눗셈 연산자 $\,$ \ $\,$ (back slash)를 사용한다.
  • X = A \ B
In [46]:
X = A \ B
X =

   2.00000
   1.00000
   1.00000

~ to be continued ~

댓글 없음:

댓글 쓰기

Numeric Analysis 4 - Numeric Linear Algebra

Numeric Analysis 4 - Numeric Linear Algebra Numeric Linear Algebra ¶ ...