给定一个日期DAY,求它是周几。
规定周一到周六为1~6,周日为0。
思路:选定一个基日,然后进行向前推到或者向后推导,模拟日期改变。
难点:要对日期分类讨论,是在基日之后,还是基日之前,对日期进行相加/相减。
#include <iostream>
using namespace std;
int monthday[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
bool isrunnian(int year){
if(year%400==0||(year%4==0&&year%100!=0)){
return true;
}
else{
return false;
}
}
void deDay(int &year,int &month,int &day){
day--;
if(day<1){
month--;
if(month<1){//月份判断要在day<1里,不然可能会导致下面的day更改发生错误。
month = 12;
year--;
}
day = monthday[isrunnian(year)][month];
}
}
void addOneDay(int &year, int &month, int &day) {
day++;
if (day > monthday[isrunnian(year)][month]) {
month++;
day = 1;
}
if (month > 12) {
year++;
month = 1;
}
}
bool isbig(int year,int month,int day){
if(year!= 2023)
return year>2023;
if(month != 10){
return month>10;
}
if(day != 10){
return day>10;
}
}
int main(){
int year,month,day;
scanf("%d-%d-%d",&year,&month,&day);
int nowy = 2023,nowm = 10,nowd = 10,noww = 2;
if(isbig(year,month,day)){
for(;;){
deDay(year,month,day);
noww++;
if(noww>6){
noww=0;
}
if(year==2023&&month==10&&day==10){
cout<<noww;
break;
}
}
}
else{
for(;;){
addOneDay(year,month,day);
noww--;
if(noww<0){
noww=6;
}
if(year==2023&&month==10&&day==10){
cout<<noww;
break;
}
}
}
return 0;
}
做完后感觉,有点太繁琐,想着有没有更简便的方式,于是查阅资料发现了大杀器——蔡勒公式。
其中:
- W 是星期数。
- c 是世纪数减一,也就是年份的前两位。
- y 是年份的后两位。
- m 是月份。m 的取值范围是 3 至 14,因为某年的 1、2 月要看作上一年的 13、14月,比如 2019 年的 1 月 1 日要看作 2018 年的 13 月 1 日来计算。这点一定要留意,在后续的代码编写要留意。
- d 是日数。
- [] 是取整运算。
- mod 是求余运算。
注意:这些符号在后面的推导中还会使用。举一个实际的计算例子:计算 2023 年 10 月 10 日是星期几。显然 c = 20,y = 23,m = 10,d = 10,带入公式计算有:
D = 5 - 40 + 23 + 5 + 35 + 10 - 1 = 37
W = 37 mod 7 = 2
验证正确。
需要注意的是:
1.D有可能计算得到的是负数!因此当为负数时候,得先+7再取余。
2.以上公式只适合于1582年10月15日之后的情形(当时的罗马教皇将恺撒大帝制订的儒略历修改成格里历,即今天使用的公历)
因此代码可以简写为:
#include <iostream>
using namespace std;
int main(){
int year,month,day;
scanf("%d-%d-%d",&year,&month,&day);
int c,y;
int D;
if(month<3){
month+=12;
year-=1;
}
c = year/100;
y = year%100;
D = c/4 - 2 * c + y + y/4 + 13*(month+1)/5 + day - 1;
int w = D;
w = w >= 0 ? ( w % 7 ) : ( w % 7 + 7 );
cout<<w<<endl;
return 0;
}