[수학 이야기 #22] 날짜를 알면 요일을 알 수 있다?!
(이미지 출처, CC0 license)
날짜와 요일의 관계
율리우스력에서 그레고리력으로의 전환
율리우스 카이사르가 도입한 율리우스력은 다음과 같은 규칙으로 날짜를 계산하였다.
- 평년은 일 이고, 4년마다 윤년 (366일)을 배치한다.
이는 굉장히 부정확한 날짜 계산법이었는데, 그 이유는 지구가 태양을 한 바퀴 돌아 제자리로 올 때까지 걸리는 시간이 약 일 이기 때문이다. 얼핏 보기에는 굉장히 작은 오차 같지만, 계산해보면 약 128년 마다 하루가 뒤쳐지게 된다.
카이사르는 기원전 1세기 사람이므로, 16세기 (약 1600년 뒤)에 들어서는 10일 정도가 원래의 날짜보다 뒤쳐지게 된다. 계속된 오차 누적을 감당할 수 없었던 교황청은 새로운 날짜 계산법을 고안해냈고, 교황 그레고리오 13세는 그 유명한 그레고리력을 제정하고 공포한다. 이는 다음과 같이 요약된다.
1582년 10월 4일 목요일 다음날을 1582년 10월 15일 금요일로 하여 오차를 한 번에 제거한다.
4의 배수인 해(년)를 윤년으로 한다. 단, 100의 배수 중 400으로 나누어 떨어지지 않는 해는 평년으로 한다.
즉 윤년을 정하는 조건을 2개 더 집어 넣어 강제로 오차를 제거한 것이다. 예를 들어서, 1700년은 100의 배수이지만 400으로 나누어 떨어지지 않기에 윤년이 아니라 평년이 된다. 마찬가지로 1800, 1900년 도 평년이지만, 2000년은 윤년이 된다.
날짜와 요일의 관계
율리우스력에서 날짜와 요일의 관계는 어떻게 될 까? 이는 다시말하면, 특정한 날짜가 주어지면 그 날짜의 요일을 대답해주는 관계식이 있냐고 묻는 것과 같다. 없을 이유가 없다...ㅋㅋ. 일단 이러한 관계식을 찾기 위해서는 요일을 문자그대로가 아닌 숫자로 인식해야 한다. 요일은 7일마다 반복되므로, 다음과 같이 인식하면 충분하다.
이렇게 인식하는 이유는, 0부터 6까지의 정수는 7로 나눈 나머지를 이루기 때문이다. 따라서 날짜
가 주어지면, 요일수
를 출력하는 공식을 만들면 된다.
평년과 요일의 관계
먼저 YYYY 꼴의 년도를 앞 두자리와, 뒤 두자리로 나눈다. 예를 들어서, 2010년이면,
1908년이면
이제 앞 두자리 수를 , 뒤 두자리수를 로 놓자. 평년은 365일 이고, 이므로, 년도가 하나 넘어갈때마다, 요일은 전년도 동일 날짜보다 하루 (나머지가 1)만큼 앞서간다. 따라서 일단 를 더하자.
윤년과 요일의 관계
4의 배수인 해는 원칙적으로 윤년이므로, 위 공식은 수정되야 한다. 어떤 수가 4의 배수일 조건은 뒤 두자리가 4의 배수일 조건과 동치이므로, 우리는 관계식에
을 더해주어야한다. 수정한 공식은 다음과 같다.
다음으로, 그레고리력에 추가된 100의 배수 조건을 살펴봐야 한다. 100의 배수인 해는 뒤의 두 자리가 00으로 끝나는 년도만 해당된다. 00으로 끝나는 해는 100년마다 돌아오고, 100년이 지날 때 마다 요일은 24번의 윤년 때문에
만큼 앞서간다. (100년전 동일 날짜에 비해) 요일이 124 만큼 앞서간다는 것은
2일 뒤쳐진다는 것과 동치이다 (-2에 주목). 100년을 앞서갔을때, 뒤의 두자리는 변하지 않으므로, 앞의 두 자리에 -2를 곱한 값을 더해
로 수정할 수 있다. 이제 400의 배수들을 생각해주자. 400의 배수인 해는 뒤 두자리는 00으로 고정되고, 앞 두자리가 4의 배수이어야 한다. 이들은 윤년이므로, 을 더해서
로 수정할 수 있다.
달과 요일의 관계
년도와 요일의 관계를 살펴봤으니, 달과 요일의 관계도 알아봐야 한다. 윤년은 2월달에 하루를 더하므로 편의상 3월을 년도의 시작으로 보고, 2월을 그 해의 마지막으로 보아, 달을 나타내는 숫자 을 다음과 같이 약속한다.
모든 달은 28일보다 크거나 같고, 28은 7의 배수여서 요일에 변화를 주지 않으므로, 28일보다 얼만큼 더 가지고 있는지 살펴보면 다음과 같다.
m | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
달 | 3월 | 4월 | 5월 | 6월 | 7월 |
일 수 | 31 | 30 | 31 | 30 | 31 |
더 가진 일 수 | 3 | 2 | 3 | 2 | 3 |
누적 | 0 | 3 | 5 | 8 | 10 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|
8월 | 9월 | 10월 | 11월 | 12월 | 1월 | 2월 |
31 | 30 | 31 | 30 | 31 | 31 | 28 |
3 | 2 | 3 | 2 | 3 | 3 | 0 |
13 | 16 | 18 | 21 | 23 | 26 | 29 |
누적 0, 3, 5, 8, 10, 13, 16, 18, 21, 23, 26, 29 를 각 달의 숫작 1,2,3,..., 12와 연관지어야 한다. 5달 마다 누적 13 만큼 늘어나므로, 이들을 연관짓는 관계식은
꼴일 것이다. 이제 상수 를 구해보자.
5개의 부등식을 모두 만족하는 의 범위는 로 좁혀진다. 편의상 로 놓자. 따라서 수정된 관계식은
이 된다.
하루와 요일의 관계
각 달 내에서, 하루하루가 지날때마다 당연히 요일도 앞당겨지므로, 일 수를 로 놓는 다면, 다음과 같이 수정해야 한다.
이제 마지막으로, 특정 값을 집어넣어서 준 식이 성립하게끔 조정해주면 끝난다. 오늘인 2018년 9월 5일은 수요일 이므로,
를 넣으면
이 나온다. 그런데 수요일은 숫자 3에 대응되므로, 관계식에 2를 더해야지만이 완성된다. 따라서,
이 완전한 관계식이다.
실제 계산
요약하면 YYYY / MM / DD 꼴의 년월일 정보로부터
: 일 수
: 달 (3월 = 1, 4월 = 2, ..., 1월 = 11, 2월 = 12)
, : 각각 년도의 앞, 뒤 두자리 (만약 1월, 2월이라면 전년도를 대신 사용한다.)
를 계산하고, 이를 식
에 대입하면 요일을 알 수 있다.
- 2020년 2월 28일: 이고 2월이므로 전년도 년을 이용하여 를 계산한다.
이므로 그 날은 금 요일이다.
- 2018년 12월 25일: 올해 크리스마스는 무슨 요일일까? 이므로
즉 화 요일이다.
질문점
만약 연도가 5자리 이상 넘어가면 어떻게 되나요? 걱정할 필요가 없다. 그때에는 년도의 앞 3자리를 로 정의하면 충분하다. 그런데, 그레고리력도 3300년 마다 1일의 오차가 존재하므로, 연도가 5자리가 되기 전 어느 시점에서는 날짜 계산의 조정이 있어야 한다. 따라서, 날짜계산의 조정이 이루어지는 시점부터 다시 위의 계산을 반복하면 된다.
출처 / 인용
[1] Burton's Elementary Number Theory 6장
마지막으로 위의 식을 파이썬 코드로 짜보면 다음과 같다.
def date_of_week(Y, M, D):
# Find m ,c, d
if int(M) < 3:
m = int(M) + 10
d = int(str(int(Y) - 1)[-2:])
c = int(str(int(Y) - 1)[0:2])
else:
m = int(M) -2
d = int(Y[-2:])
c = int(Y[0:2])
# Find k
k = int(D)
L = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday']
w = (d + (d//4) + (c//4) + (13*m-1)//5 -2*c + k) % 7
return 'The date of the week is ' + L[w] + '!'
#---------------------
Y, M, D = input('Enter the date in YYYY/MM/DD form: ').split('/')
print (date_of_week(Y,M,D))
마지막 파이썬 코드까지... 크 공대 감성
읽어주셔서 감사합니다 ㅜㅜ
ㅋㅋㅋ 제목 보고 딱 저책이 바로 떠올랐네요 ㅎㅎ
ㅋㅋㅋㅋ 예리하십니다
음 저런 복잡한 공식도 있지만
암산으로 계산하려면
100년단위로 특정 날짜를 외우고
그 날짜 앞뒤로 차이만큼 나눗셈과 나머지로 구할 수 있다고 합니다.
그렇게도 구할 수 있겠네요. 읽어주셔서 감사합니다!
짱짱맨 출석부 호출로 왔습니다.
즐거운 하루 되세요..
감사합니다!
이오스 계정이 없다면 마나마인에서 만든 계정생성툴을 사용해보는건 어떨까요?
https://steemit.com/kr/@virus707/2uepul