C++알고리즘 계열 의 달력 생 성 알고리즘 코드

달력 은 우리 생활 에서 매우 중요 한 역할 을 하 는데 출근,학교,데이트 모두 달력 을 떠 날 수 없다.매년 새해 부터 사람들 은 새로운 달력 을 바 꿔 야 합 니 다.앞으로 1 년 동안 이렇게 많은 날 이 어떻게 확정 되 었 는 지 알 고 싶 습 니까?왜 작년 의 국경일 은 금요일 이 고 올해 의 국경일 은 수요일 입 니까?그럼 달력 알고리즘 을 연구 해 보 세 요.본 고 는 달력 의 편성 규칙 을 소개 하고 어느 날 이 무슨 요일 인지 계산 하 는 방법 과 컴퓨터 에서 어느 해 의 달력 을 인쇄 하 는 방법 을 확정 할 것 이다.
달력 알고리즘 을 연구 하려 면 먼저 달력 의 편성 규칙,즉 역법 을 알 아야 한다.역법 이란 년,월,일의 시간 길이 와 그들의 관 계 를 추산 하고 시간 서열 을 지정 하 는 법칙 을 말한다.우리 나라 의 공식 역법 은 중국 양력,즉 세계 적 으로 통용 되 는 그 레 고리 안 캘 린 더(Gregorian Calendar)로 중국 양력 의 연 도 는 평년 과 윤년 으로 나 뉘 는데 평년 은 365 일,윤년 은 366 일이 다.1 년 이 평년 인지 윤년 인지 판정 하 는 규칙 은 다음 과 같다.
1、  연도 가 4 의 배수 이 고 100 의 배수 가 아니라면 윤년 이다.
2、  만약 연도 가 400 의 배수 라면 윤년 이다.
3、  1,2 조건 을 충족 시 키 지 못 하 는 것 이 평년 이다.
한 마디 로 4 년 에 한 번 윤달 하고 백 년 에 윤달 하지 않 으 며 400 년 에 다시 윤달 하 다 는 것 이다.
중국 양력 의 달 에 관 한 규칙 은 이 렇 습 니 다.1 년 은 12 개 월 로 나 뉘 는데 그 중에서 1 월,3 월,5 월,7 월,8 월,10 월 과 12 월 은 큰 달 이 고 한 달 은 31 일이 있 습 니 다.4 월,6 월,9 월,11 월 은 작은 달 이 고 한 달 에 30 일이 있다.2 월 일 수 는 윤년 인지 여부 에 따라 정 해 야 하 며 윤년 이 라면 2 월 이 29 일,평년 이 라면 2 월 이 28 일이 다.
년 월 일 을 제외 하고 사람들의 일상생활 에서 날짜 에 대해 또 다른 속성 을 정 의 했 는데 그것 이 바로 무슨 요일 입 니까?주 는 양력 의 범주 안에 있 는 것 이 아니 지만 사람들 은 주 로 시간 을 관리 하고 계획 하 는 것 에 익숙 하 다.예 를 들 어 일주일 에 5 일 을 일 하고 이틀 을 쉬 는 등 주의 규칙 은 사람들의 생활 습관 을 철저하게 바 꾸 었 기 때문에 주 는 이미 역법 중의 일부분 이 되 었 다.요일 의 명명 은 최초 로 고대 바빌론 문화 에서 기원 되 었 다.기원전 7-6 세기 에 바빌론 사람들 은 주 제 를 사 용 했 고 일주일 동안 매일 신 이 다스 렸 다.이 규칙 은 나중에 고대 로마 로 전해 져 현재 의 요일 제도 로 발전 되 었 다.
어느 날 이 도대체 무슨 요일 인지 어떻게 압 니까?달력 을 찾 는 것 외 에 어느 날 이 무슨 요일 인지 추산 할 방법 이 있 습 니까?답 은 긍정 적 이다.주 는 해 와 달 처럼 고정된 역법 규칙 이 있 지 는 않 지만 주의 계산 에 도 규칙 이 있다.주 는 정 해진 7 일 주기 로 그 배열 순 서 는 윤년,평년,그리고 크 고 작은 달의 일수 변화 에 영향 을 주지 않 는 다.따라서 어느 날 이 무슨 요일 인지 정확히 알 면 다른 날 이 무슨 요일 인지 추산 할 수 있다.추산 하 는 방법 은 매우 간단 하 다.바로 두 날짜 사이 에 며칠 차이 가 나 는 지 계산 하고 차이 가 나 는 일수 로 7 을 나머지 로 하 는 것 이다.이 나머지 는 두 날짜 의 요일 차이 이다.예 를 들 어 1977 년 3 월 27 일이 일요일 이라는 것 을 알 았 다 고 가정 하면 1978 년 3 월 27 일이 무슨 요일 인지 어떻게 알 수 있 습 니까?앞의 방법 에 따 르 면 1977 년 3 월 27 일부 터 1978 년 3 월 27 일 사이 의 차 이 는 365 일,365 를 7 로 나 누 면 1 이 므 로 1978 년 3 월 27 일이 월요일 이다.
상술 한 방법 으로 요일 을 계산 하 는 관건 은 두 날짜 사이 의 일 수 를 구 하 는 것 이다.두 날짜 사이 의 일 수 를 계산 하 는 데 자주 사용 되 는 방법 은 두 가지 가 있 는데 하 나 는 양력 의 달 과 해 의 규칙 을 이용 하여 직접 계산 하 는 것 이 고 다른 하 나 는 유 략 일 을 이용 하여 계산 하 는 것 이다.양력 규칙 을 이용 하여 두 날짜 사이 의 차 이 를 직접 계산 합 니 다.쉽게 말 하면 두 날짜 사이 의 차 이 를 세 부분 으로 나 누 는 것 입 니 다.앞의 날짜 가 있 는 년도 에 남 은 일수,두 날짜 사이 에 있 는 정수 년 에 포 함 된 일수 와 뒤의 날짜 가 있 는 년도 의 지난 일수 입 니 다.만약 두 날짜 가 서로 인접 한 두 해 의 날짜 라면 두 번 째 부분의 일년 일 수 는 0 이다.1977 년 3 월 27 일부 터 2005 년 5 월 31 일 까지 의 경우 1977 년 남 은 일 수 는 279 일,중간 정수 년 은 1978 년 부터 2005 년(2005 년 제외)까지 총 26 년 으로 윤년 7 개 와 평년 20 개 를 포함해 총 9 천 862 일,마지막 으로 2005 년 1 월 1 일부 터 5 월 31 일 까지 거 친 일수 151 일이 다.삼자 총 결 10292 일.양력 규칙 을 직접 이용 하여 날짜 차이 일 수 를 계산 하 는 알고리즘 은 다음 과 같다.

int CalculateDays(int ys, int ms, int ds, int ye, int me, int de)
 {
 int days = CalcYearRestDays(ys, ms, ds);
 if(ys != ye) /*        */
 {
 if((ye - ys) >= 2) /*      ,          */
 {
 days += CalcYearsDays(ys + 1, ye);
 }
 days += CalcYearPassedDays(ye, me, de);
 }
 else
 {
 days = days - CalcYearRestDays(ye, me, de);
 }
 return days;
 }
/*          ,        */
 int CalcYearPassedDays(int year, int month, int day)
 {
 int passedDays = 0;
 int i;
 for(i = 0; i < month - 1; i++)
 {
 passedDays += daysOfMonth[i];
 }
 passedDays += day;
 if((month > 2) && IsLeapYear(year))
 passedDays++;
 return passedDays;
 }
/*           ,         */
 int CalcYearRestDays(int year, int month, int day)
 {
 int leftDays = daysOfMonth[month - 1] - day;
 int i;
 for(i = month; i < MONTHES_FOR_YEAR; i++)
 {
 leftDays += daysOfMonth[i];
 }
 if((month <= 2) && IsLeapYear(year))
 leftDays++;
 return leftDays;
 }
 
/*
   years 1 1  yeare 1 1      ,
   years 1 1 ,     yeare 1 1 
 */
 int CalcYearsDays(int years, int yeare)
 {
 int days = 0;
 int i;
 for(i = years; i < yeare; i++)
 {
 if(IsLeapYear(i))
 days += DAYS_OF_LEAP_YEAR;
 else
 days += DAYS_OF_NORMAL_YEAR;
 }
 return days;
 }
또 다른 두 날짜 차이 일 수 를 계산 하 는 방법 은 유략 일(Julian Day,JD)을 이용 해 계산 하 는 것 이다.먼저 유 략 일 을 소개 합 니 다.유 략 일 은 년 을 기억 하지 않 고 달 을 기억 하지 않 으 며 일 만 기억 하 는 역법 입 니 다.프랑스 학자 Joseph Justus Scaliger(1540-1609)가 1583 년 에 제기 한 일수 단위 의 흐 르 는 달력 입 니 다.유 략 일 은 유 략 력(Julian Calendar)과 아무런 관계 가 없 으 며,유 략 일 이 라 고 명명 한 것 도 그의 아버지 인 DD 이탈리아 학자 인 Julius Caesar Scaliger(1484-1558)를 기념 하기 위해 서다.쉽게 말 해,유 략 일 은 기원전 4713 년 1 월 1 일 UTC 12:00 부터 거 친 일 수 를 뜻 하 며,JD0 은 기원전 4713 년 1 월 1 일 12:00 부터 기원전 4713 년 1 월 2 일 12:00 사이 의 24 시간 으로 순차적으로 지 정 돼 하루 에 하나의 유일한 숫자 가 부여 된다.예 를 들 어 1996 년 1 월 1 일 12 시 부터 시 작 된 날 이 바로 유 략 일 JD 2450084 였 다.유 략 일 을 사용 하면 서로 다른 역법 의 연 표를 통일 시 켜 각종 역법 에서 날 짜 를 거 슬러 올 라 갈 수 있다.만약 두 날짜 사이 의 일 수 를 계산한다 면,유 략 일 을 이용 하여 계산 하 는 것 도 매우 편리 하 다.먼저 두 날짜 의 유 략 일 수 를 계산 한 다음 에 바로 상쇄 하면 두 날짜 사이 의 일 수 를 얻 을 수 있다.
양력 의 날짜 로 유 략 일 수 를 계산 하 는 것 은 매우 간단 한 일이 다.여러 가지 공식 으로 유 략 일 을 계산 할 수 있다.본 고 는 다음 과 같은 공식 을 선택 하여 유 략 일 을 계산한다.
 
그 중에서 y 는 년도 이 고 m 는 월 이 며 d 는 날짜 이 며 m 가 2 보다 작 거나 같 으 면 m 는 m+12 로 수정 되 며 년도 수정 은 y-1 이다.c 값 은 다음 과 같은 방법 으로 계산 합 니 다.
 
다음은 양력 날짜 로 유 략 일 을 계산 하 는 알고리즘 입 니 다.

int CalculateJulianDay(int year, int month, int day)
{
 int B = 0;
 if(month <= 2)
 {
 month += 12;
 year -= 1;
 }
 if(IsGregorianDays(year, month, day))
 {
 B = year / 100;
 B = 2 - B + year / 400;
 }
 double dd = day + 0.5000115740; /*  12:00         (    )*/
 return int(365.25 * (year + 4716) + 0.01) + int(30.60001 * (month + 1)) + dd + B - 1524.5;
}
유 략 일의 계산 은 보통 초 까지 정확 하고 얻 은 JD 수도 부동 소수점 이다.본 고 는 날짜 가 떨 어 진 정수 일 수 를 계산 하기 위해 정수 로 계산한다.유 략 일의 주기 시작 과 매일 낮 12 시,역법 중의 일 수 는 보통 0 시 부터 시작 되 기 때문에 유 략 일 계산 에 서 는 날짜 의 일 수 를 수정 하 였 다.1977 년 3 월 27 일의 유 략 일 은 2443230 이 었 고 2005 년 5 월 31 일의 유 략 일 은 2453522 이 며 차 이 는 10292 로 앞의 방법 으로 계산 한 결과 와 일치 했다.
우 리 는 두 가지 방법 으로 두 날짜 사이 의 일 수 를 모두 10292 로 계산 해 냈 다.현재 10292 를 7 로 나 누 면 나머지 는 2 이다.즉 2005 년 5 월 31 일과 1977 년 3 월 27 일 은 이틀 차이 가 나 기 때문에 2005 년 5 월 31 일이 화요일 이다.
상술 한 요일 계산 방법 은 절차 가 간단 하지만 매번 두 날짜 의 시간 차 를 계산 하 는 것 은 매우 편리 하지 않다.날짜 에 맞 는 주 를 직접 계산 할 수 있 는 공식 이 있다 면 더 좋 지 않 겠 습 니까?다행히도 이런 공식 은 존재 한다.다음 편 에 서 는 공식 법 이 하루 주 수 를 직접 계산 하 는 알고리즘 을 계속 소개 한다.
작은 지식 1:양력 의 윤년
중국 양력(즉 그 리 력)의 치 윤 규칙 은 4 년 에 한 번 윤달 이 고 백 년 에 윤달 하지 않 으 며 400 년 에 다시 윤달 하 는 것 인 데 왜 이렇게 이상 한 치 윤 규칙 이 있 을 까?이것 은 실제로 천체 운행 주기 와 인류 가 정의 한 역법 주기 간 의 오차 와 관계 가 있다.지구 가 태양 주 위 를 도 는 주 기 는 365.242 일,즉 하나의 회귀 년(Tropical Year)인 데 양력 의 1 년 은 365 일 로 이렇게 한 해 가 회귀 년 보다 0.2422 일 짧 아 졌 고,4 년 이 쌓 이면 0.9688 일(약 1 일)이 더 많아 져 윤년 이 설 치 됐 는데,이 해 는 하루 가 더 많 았 다.이렇게 되면 4 개 양력 년 이 4 개 회귀 년 보다 0.0312 일 더 많아 져 매년 평균 0.0078 일이 많아 지면 400 년 이 지나 면 3.12 일이 더 많아 진다.즉,400 년 마다 3 개의 윤년 을 줄 여야 한 다 는 것 이다.그래서 백년 불 윤,400 년 재 윤 의 치 윤 규칙 을 만 들 었 다.
실제로 양력 의 윤달 은 수치 가 큰 해 에 3200 을 제거 할 수 있 고 172800 을 제거 할 수 있다 면 윤년 이라는 규칙 도 있다.앞 으로 는 400 년 의 윤년 에 도 0.12 일이 더 많아 져 하루 평균 0.0003 일이 더 많아 졌 기 때문에 3200 년 마다 0.96 일이 더 많아 졌 다.즉,3200 년 마다 윤년 이 하나 더 줄 어 들 기 때문에 3200 년 에 정 제 될 수 있 는 해 는 윤년 이 아니 기 때문이다.그러나 오 차 는 끝나 지 않 았 다.3200 년 마다 윤년(하루 감소)이 줄 어 들 었 다.실제로 0.04 일 더 줄 었 다.이 오 차 는 계속 누적 계산 해 야 한다.이것 은 본 고의 범 위 를 넘 어 관심 이 있 는 독자 들 이 스스로 계산 할 수 있다.
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기