제어 흐름
조건부 제어 — if, else, switch
조건문을 사용하면 런타임에 실행할 코드 블록을 선택할 수 있습니다. 가장 단순한 형태의 조건문은 if
문입니다. 예를 들면 다음과 같습니다.
% Generate a random number a = randi(100, 1); % If it is even, divide by 2 if rem(a, 2) == 0 disp('a is even') b = a/2; end
if
문은 키워드(선택 사항) elseif
또는 else
를 사용하여 다른 선택 항목을 포함할 수 있습니다. 예를 들면 다음과 같습니다.
a = randi(100, 1); if a < 30 disp('small') elseif a < 80 disp('medium') else disp('large') end
또는, 알고 있는 일련의 값과 같은지 테스트하려는 경우 switch
문을 사용합니다. 예를 들면 다음과 같습니다.
[dayNum, dayString] = weekday(date, 'long', 'en_US'); switch dayString case 'Monday' disp('Start of the work week') case 'Tuesday' disp('Day 2') case 'Wednesday' disp('Day 3') case 'Thursday' disp('Day 4') case 'Friday' disp('Last day of the work week') otherwise disp('Weekend!') end
if
와 switch
모두에 대해 MATLAB®에서는 첫 번째 true 조건에 해당하는 코드를 실행하고 코드 블록을 종료합니다. 각각의 조건문에는 end
키워드가 필요합니다.
알고 있는 이산 값이면서 값의 개수가 많을 때는 일반적으로 switch
문을 사용하는 편이 if
문을 사용하는 것보다 읽기 편합니다. 하지만 switch
값과 case
값 간에 부등식을 테스트할 수는 없습니다. 예를 들어, 다음과 같은 조건 유형은 switch
로는 구현할 수 없습니다.
yourNumber = input('Enter a number: '); if yourNumber < 0 disp('Negative') elseif yourNumber > 0 disp('Positive') else disp('Zero') end
조건문의 배열 비교
관계 연산자와 if
문이 행렬에 대해 동작하는 방식을 이해하는 것은 중요합니다. 두 변수 간의 등식을 확인하려는 경우 다음을 사용해야 할 수 있습니다.
if A == B, ...
이는 유효한 MATLAB 코드이며, A
와 B
가 스칼라일 경우 예상대로 동작합니다. 하지만 A
와 B
가 행렬인 경우 A == B
는 이 두 행렬이 같은지 여부를 테스트하지 않으며 두 행렬의 어느 부분이 같은지를 테스트합니다. 그 결과로, 요소별 동일성을 나타내는 0과 1로 구성된 또 다른 행렬이 만들어집니다.
A = magic(4); B = A; B(1,1) = 0; A == B ans = 4×4 logical array 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
두 변수 간의 동일성을 확인하는 올바른 방법은 isequal
함수를 사용하는 것입니다.
if isequal(A, B), ...
isequal
은 if
함수 실행 결과로, 행렬 대신 스칼라 논리값 1
(true
에 해당) 또는 0
(false
)을 반환합니다. 위의 A
행렬과 B
행렬을 사용하면 다음과 같은 결과를 얻게 됩니다.
isequal(A,B) ans = logical 0
다음은 이러한 부분을 보다 중점적으로 설명하기 위한 또 다른 예제입니다. A
와 B
가 스칼라인 경우 다음 프로그램은 절대 “예기치 못한 상황”에 도달하지 않습니다. 하지만 이전에 소개한, 열을 서로 교환한 마방진을 포함해 대부분의 행렬 쌍에서는 A > B
, A < B
, A == B
중 어떤 행렬 조건도 모든 요소에 대해 true가 아니므로 else
절이 실행됩니다.
if A > B 'greater' elseif A < B 'less' elseif A == B 'equal' else error('Unexpected situation') end
다음을 포함한 여러 함수가 if
조건 사용 시 행렬 비교 결과를 스칼라 조건으로 줄이는 데 도움이 됩니다.
isequal isempty all any
루프 제어 — for, while, continue, break
이 섹션에서는 프로그램 루프를 제어하는 다음 MATLAB 함수에 대해 다룹니다.
for
for
루프는 특정 명령문 그룹을, 미리 지정한 고정 횟수만큼 반복해서 실행합니다. 이와 짝을 이루는 end
는 해당 명령문의 끝을 표시합니다.
for n = 3:32 r(n) = rank(magic(n)); end r
내부 명령문이 세미콜론으로 끝나면 출력이 반복해 표시되지 않으며, 루프 뒤에 r
이 있으면 최종 결과만 표시됩니다.
특히, 루프가 중첩되어 있는 경우에는 가독성을 높이기 위해 루프를 안쪽으로 들여쓰는 것이 좋습니다.
for i = 1:m for j = 1:n H(i,j) = 1/(i+j); end end
while
while
루프는 논리 조건의 제어에 따라 특정 명령문 그룹을 무한으로 반복해서 실행합니다. 이와 짝을 이루는 end
는 해당 명령문의 끝을 표시합니다.
다음은 구간 이분법을 사용하여 다항식의 해를 찾는 완전한 프로그램으로, 여기에는 while
, if
, else
, end
가 포함되어 있습니다.
a = 0; fa = -Inf; b = 3; fb = Inf; while b-a > eps*b x = (a+b)/2; fx = x^3-2*x-5; if sign(fx) == sign(fa) a = x; fa = fx; else b = x; fb = fx; end end x
그 결과로 다음과 같이 다항식 x3 – 2x – 5의 근을 얻게 됩니다.
x = 2.09455148154233
if
문에 대한 섹션에 설명된 행렬 비교 관련 주의 사항은 while
문에도 적용됩니다.
continue
continue
문은 for
루프 또는 while
루프에서 루프 본문의 나머지 명령문을 건너뛰고 다음 번 반복 위치로 제어를 전달합니다. 이는 중첩 루프에 있는 continue
문의 경우에도 마찬가지입니다. 즉, continue
문이 발견된 루프의 시작 부분에서 실행이 계속 진행됩니다.
아래 예제에서는 파일 magic.m
에서 모든 비어 있는 라인과 주석을 건너뛰고 코드 라인 수를 세는 continue
루프를 보여줍니다. continue
문은 비어 있는 라인이나 주석 라인이 발견될 때마다 개수를 늘리지 않고 magic.m
의 다음 라인으로 이동하는 데 사용됩니다.
fid = fopen('magic.m','r'); count = 0; while ~feof(fid) line = fgetl(fid); if isempty(line) || strncmp(line,'%',1) || ~ischar(line) continue end count = count + 1; end fprintf('%d lines\n',count); fclose(fid);
break
break
문을 사용하면 for
루프 또는 while
루프가 조기에 종료됩니다. 중첩 루프의 경우 break
는 해당 루프만 조기에 끝냅니다.
다음은 이전 섹션에서 다룬 예제를 개선한 것입니다. 여기에 break
를 사용하는 것이 좋은 이유는 무엇일까요?
a = 0; fa = -Inf; b = 3; fb = Inf; while b-a > eps*b x = (a+b)/2; fx = x^3-2*x-5; if fx == 0 break elseif sign(fx) == sign(fa) a = x; fa = fx; else b = x; fb = fx; end end x
프로그램 종료 — return
이 섹션에서는 실행이 완료되기 전에 프로그램을 종료하는 데 사용할 수 있는 MATLAB return
함수에 대해 다룹니다.
return
return
은 명령의 현재 시퀀스를 종료하고 호출 함수 또는 키보드로 제어를 반환합니다. 또한 return
은 keyboard
모드를 종료하는 데에도 사용됩니다. 호출된 함수는 일반적으로 함수 끝에 도달하면 호출한 함수에 제어를 전달합니다. 호출된 함수 내에 return
문을 삽입하여 강제로 조기에 종료되도록 하고 호출한 함수로 제어를 전달할 수 있습니다.
벡터화
MATLAB 프로그램의 실행 속도를 높이기 위한 한 가지 방법은 프로그램을 구성할 때 사용하는 알고리즘을 벡터화하는 것입니다. 다른 프로그래밍 언어에서는 for
루프나 DO
루프를 사용할 수 있는 데 비해 MATLAB에서는 벡터 연산 또는 행렬 연산을 사용할 수 있습니다. 로그 테이블을 생성하는 간단한 예를 하나 들어보겠습니다.
x = 0.01; y = log10(x); for k = 1:999 x(k+1) = x(k) + 0.01; y(k+1) = log10(x(k+1)); end
이와 동일한 코드의 벡터화된 버전은 다음과 같습니다.
x = .01:.01:10; y = log10(x);
좀 더 복잡한 코드의 경우에는 벡터화로 프로그래밍하는 게 더 어려울 수 있습니다.
사전할당(Preallocation)
코드의 일부를 벡터화할 수 없는 경우 출력 결과가 저장되는 벡터나 배열을 사전에 할당해 놓는 방식으로 for
루프의 실행 속도를 높일 수 있습니다. 예를 들어, 이 코드에서는 함수 zeros
를 사용하여 for
루프에서 생성될 벡터를 사전에 할당해 놓습니다. 이렇게 하면 for
루프의 실행 속도가 훨씬 빨라지게 됩니다.
r = zeros(32,1); for n = 1:32 r(n) = rank(magic(n)); end
위의 예제에서 사전할당을 사용하지 않으면 MATLAB 인터프리터에서는 루프를 돌 때마다 요소 하나씩, r
벡터를 확장하게 됩니다. 벡터 사전할당을 활용하면 이 단계를 수행할 필요가 없어 실행 속도가 빨라집니다.