【#文档大全网# 导语】以下是®文档大全网的小编为您整理的《公历历法》,欢迎阅读!
【公历历法】
公历历法很简单,年有润年(LeapYear)和平年之分,平年每月天数恒为: 月份 一 二 三 四 五 六 七 八 九 十 十一 十二 天数 31 28 31 30 31 30 31 31 30 31 30 31 共365天。润年366天,二月多一天,29天。
【润年判断】
如果年份数能被4整除但不能被100整除或者能被400整除者,为润年。
【400年刚好一个轮回】
很容易想到每400年内的润年数相等,即刚好一个轮回,400年有多少个润年?被4整除的有100个,被100整除的有4个,被400整除的只有1个,所以一共有100-4+1=97个润年,所以400年共有(365*400+97)天,即146097天,除7余0!
也就是说2001年1月1日的星期数与1年1月1日的星期数相同,翻出日历一看,星期一,我不知道上帝什么时候造的人,或许是1年1月1日。这样一来,任何一个日期我们都可以把它折算到0~399年之内的日期来算,0年的说法不准确,或许没有,但不影响这个数学结论,我们只是借它来推一推而已。
【起初的400年】
如果每一年都是平年,即365天,除7余1,也就是说如果不遇上润年,每往下一年就会使星期数增一。同样的道理,如果遇上润年,则多增一。我们要算的也就是把润年数算出来就行了,很容易,如果是y年(0<=y<400),则遇到的润年数为[y/4]-[y/100]+1,为什么要+1,因为0年也是润年(被400整除),然后把y自己身加起来就得到年指数:(y+[y/4]-[y/100])%7,它影响着星期的轮转。(其中[]表示取整,%表示取余,%7表示除以7得到的余数)
【月份的变迁】
月份的天数也不一定,所以不好直接用数学公式来表示,所以列一个表,表中对应数为星期的月指数。前面有数据:(假设为平年)
月份 一 二 三 四 五 六 七 八 九 十 十一 十二 天数 31 28 31 30 31 30 31 31 30 31 30 31 每月对应前面过去的天数: 月份 一 二 三 …… 天数 0 31 31+28 …… 对天数对7除取余得:
月份 一 二 三 四 五 六 七 八 九 十 十一 十二 天数 0 3 3 6 1 4 6 2 5 0 3 5 用一个数组保存下来:
R[13]={0,0,3,3,6,1,4,6,2,5,0,3,5};
设月为m,则月份的影响指数为R[m],它影响着星期的轮转。
【全部加起来取7的余数】
最后剩下天指数,这很容易,直接加起来就行了,所以最后得到一个总的表达式:(先把年对400除取其余数:Year=Year%400)
Week=(Year+[Year/4]-[Year/100]+R[Month]+Day+C)%7
最后有一个常数C,如何确定这个常数,拿一个平年的正常日期数代进来,和星期数比较就可以确定C。
如2001年1月1日是星期一,所以(1+0-0+0+1+C)%7=1,即(2+C)%7=1 ==> C=6。
【遇到润年C会变】
如果没有拿足够的数据来验证,我不敢说C是常数。举几个例子:
2000年1月1日星期六,如果C=6,按公式算出来:(0+0-0+0+1+6)%7=0,星期天,错了一天,哪里错了?
前面算月指数的时候是按平年来算的,如果遇到润年,多的一天是在2月29日,如果在这之前的日期,润年不润,所以年指数会多算一天,如果在这之后,润年已润,年指数已经计算在内,所以月指数同样按平年来算不误,如2000年5月1日星期一,按公式:(0+0-0+1+1+6)%7=1,完全正确。
所以改进的做法是先判断是否是在润年而且月份数小于3,如果是,则C=5,否则C=6。
流程图
#include //包含stdio函数库
int week(int y,int m,int d); //子函数week声明,因为子函数在主函数之前故需要声明
int main() //主函数 {
char wk[7][3] = {{"天"},{"一"},{"二"},{"三"},{"四"},{"五"},{"六"}}; //字符数组定义
int year, month, day, w; //年、月、日变量定义
scanf("%d %d %d", &year, &month, &day); //输入年、月、日
w = week(year, month, day); //子函数调用
printf("%d年%d月%d日 星期%s", year, month, day, wk[w]); //格式输出:XX年XX月XX日 星期X }
int week(int y,int m,int d) //子函数week函数体 {
static int r[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //静态数组 int c,w; //变量定义
y %= 400; //判断是否为闰年
if ((y==0||y%4==0&&y%100!=0)&&m<3) //基姆拉尔森计算公式计算星期几 c = 5; else c = 6;
w = (y+y/4-y/100+r[m]+d+c)%7;
return w; //返回计算得的星期几结果 }
关键函数部分第一位解答得很详细嘛~~~~
本文来源:https://www.wddqxz.cn/22a4751a6c85ec3a87c2c5a8.html