본문 바로가기

프로그램/MATLAB

【MATLAB】 지나간 날짜를 구하는 문제 풀이

- Chapra의 응용수치해석 연습문제 3.16

[문제]

어떤 년도에서 지나간 날짜를 구하는 M-파일 함수를 개발하라. 이 함수의 첫번째 줄은 다음과 같이 설정한다.


여기서 mo는 달(1-12), da는 일(1-31), 그리고 leap는 평년일 때는 0이고 윤년일 때는 1이다. 1997년 1월 1일, 2004년 2월 29일, 2001년 3월 1일, 2004년 6월 21일, 그리고 2008년 12월 31일에 대해 이 프로그램을 검증하라.

*힌트 : 이를 위한 좋은 방법은 for와 switch 구조를 결합시키는 것이다.


[문제풀이]

먼저, '윤년'이라는 개념이 사용되었습니다. 윤년은 4년마다 2월 29일로 함으로써 4년간의 연평균 일수를 365.25일로 만들어주는 개념입니다. 시간이 지날수록 계절과 맞지 않는 것을 방지하기 위해 만들어진 것입니다. 그리고 가장 외우기 쉬운 윤년은 2000년입니다. 2000년을 기준으로 +-4년을 하면 윤년이 됩니다. 문제에서 주어진 2004년, 2008년이 윤년이 됩니다. 그럼 이 경우에 leap가 1이 되는 경우입니다. (반대로 윤년이 아닌 경우에는 문제에서 주어진 것처럼 leap가 0이 됩니다.)

잠깐, 문제에서 주어진 함수와 변수를 다시 보겠습니다.
(1) 함수이름 : days → 날짜들을 구하기 위한 적절한 함수명입니다.
(2) mo : month 의 앞글자 2개만 따온 듯합니다. '월'을 뜻합니다.
(3) da : day의 앞글자 2개만 따온 듯합니다. '일'을 뜻합니다.
(4) leap : 윤년이 영얼 'leap year'라고 합니다.

그리고 문제에서 힌트로써 for, switch 구조를 결합(내포)해서 사용하는 것을 추천해주고 있습니다. 그 방법 그대로 진행해보겠습니다.


위 사진이 전체 코드입니다. 함수를 통해서 최종적으로 구하고자 하는 변수는 nd입니다. 문제에서 원하는 '지나간 날짜'가 nd가 되는 것입니다. 우선, 처음에 nd를 0으로 초기화해주었습니다. (처음에 초기화하지 않고 바로 for 구조로 넘어갔는데, 17번째 줄에서 nd에 mdays를 더해서 넣어주는 과정에서 nd의 값이 지정되어 있지 않았기 때문에 계산되지 않았던 것 같습니다.)


전체적으로 보면, for 구조로 mo-1달 만큼(구하고자하는 달의 바로이전 달까지) 반복시켜주면서 그 내에 매월마다 다른 일수를 가진 것들을 switch~case를 통해서 각각 일수를 구해줍니다. 그리고 마지막에 for구문 안에서 nd에 값들을 임시로 저장해줍니다. 이렇게 하는 이유는 각 달마다 일수가 달라서이기 때문이고 이때 switch 구문을 사용함으로써 while보다는 쉽게 작성할 수 있어서 입니다. 만약 while 구문으로 작성한다면, 조건을 입력해주어야 하는데, 위에서 case {조건}에 적혀있는 것처럼 그다지 좋은 조건을 한번에 작성하기가 힘들다는 것을 알 수 있습니다.

1,3,5,7,8,10,12월은 매월 31일이므로, mdays에 31일이라는 숫자를 삽입해주고 (이때, mdays는 최종적으로 nd를 구하기위해서 중간 계산용으로 삽입된 변수라고 생각하시면 편합니다. 왜냐, 함수 내에서는 사용이 되지만, 입력도 출력도 아닌 값이기 때문입니다.) 4,6,9,11월에는 30일을, 2월에는 윤년일 때만 1을 더해주기 위해서 위와 같이 윤년의 경우에 1로 지정되는 leap 변수를 더해주어 2월을 29일로 계산하게 합니다. 윤년의 개념은 앞에서 말씀드렸습니다.


그리고 함수 마지막에 20번째 줄에 알고자하는 일(da)의 숫자까지 더해주게 되면 총 지나간 날짜의 합이 됩니다. 변수 da가 갑자기 나온 것이 아닙니다. 제일 위에 보시면 변수 (3)번에서 소개해드렸습니다. "(3) da : day의 앞글자 2개만 따온 듯합니다. '일'을 뜻합니다."


이제 출력을 해보겠습니다. 문제에서 아래의 5가지 경우에 대해서 검증해보라고 하였습니다.

(1) 1997년 1월 1일
(2) 2004년 2월 29일 (→ 윤년, leap =1)
(3) 2001년 3월 1일
(4) 2004년 6월 21일 (→ 윤년, leap =1)
(5) 2008년 12월 31일 (→ 윤년, leap =1)

출력하기 위해 함수이름과 함께 days(월, 일, 윤년) = days(mo, da, leap) 처럼 명령을 입력해줍니다. 당연히 윤년이 아닌 날에는 leap 값이 0이 됩니다.


위와 같이 검증할 수 있었습니다. 위에서 년도의 값은 사용자가 미리 윤년인지 아닌지 판단한 후에 넣어줘야합니다. 이상!