c语言详解 蔡勒(Zeller)公式计算某一天是星期几 极其方便
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c语⾔详解 蔡勒(Zeller)公式计算某⼀天是星期⼏ 极其
⽅便
1. —— 蔡勒(Zeller)公式
历史上的某⼀天是星期⼏?未来的某⼀天是星期⼏?关于这个问题,有很多计算公式(两个通⽤计算公式和⼀些分段计算公式),其中最著名的是蔡勒(Zeller)公式。
即w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
公式中的符号含义如下,w:星期;c:世纪-1;y:年(两位数);m:⽉(m⼤于等于3,⼩于等于14,即在蔡勒公式中,某年的1、2⽉要看作上⼀年的13、14⽉来计算,⽐如2003年1⽉1⽇要看作2002年的13⽉1⽇来计
算);d:⽇;[ ]代表取整,即只要整数部分。
(C是世纪数减⼀,y是年份后两位,M是⽉份,d是⽇数。
1⽉和2⽉要按上⼀年的13⽉和14⽉来算,这时C和y均按上⼀年取值。
)
算出来的W除以7,余数是⼏就是星期⼏。
如果余数是0,则为星期⽇。
以2049年10⽉1⽇(100周年国庆)为例,⽤蔡勒(Zeller)公式进⾏计算,过程如下:
蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
=49+[49/4]+[20/4]-2×20+[26× (10+1)/10]+1-1
=49+[12.25]+5-40+[28.6]
=49+12+5-40+28
=54 (除以7余5)
即2049年10⽉1⽇(100周年国庆)是星期5。
你的⽣⽇(出⽣时、今年、明年)是星期⼏?不妨试⼀试。
不过,以上公式只适合于1582年10⽉15⽇之后的情形(当时的罗马教皇将恺撒⼤帝制订的儒略历修改成格⾥历,即今天使⽤的公历)。
过程的推导:(对推理不感兴趣的可略过不看)
星期制度是⼀种有古⽼传统的制度。
据说因为《圣经·创世纪》中规定上帝⽤了六
天时间创世纪,第七天休息,所以⼈们也就以七天为⼀个周期来安排⾃⼰的⼯作和⽣
活,⽽星期⽇是休息⽇。
从实际的⾓度来讲,以七天为⼀个周期,长短也⽐较合适。
所
以尽管中国的传统⼯作周期是⼗天(⽐如王勃《滕王阁序》中说的“⼗旬休暇”,即是
指官员的⼯作每⼗⽇为⼀个周期,第⼗⽇休假),但后来也采取了西⽅的星期制度。
在⽇常⽣活中,我们常常遇到要知道某⼀天是星期⼏的问题。
有时候,我们还想知
道历史上某⼀天是星期⼏。
通常,解决这个⽅法的有效办法是看⽇历,但是我们总不会
随时随⾝带着⽇历,更不可能随时随⾝带着⼏千年的万年历。
假如是想在计算机编程中
计算某⼀天是星期⼏,预先把⼀本万年历存进去就更不现实了。
这时候是不是有办法通
过什么公式,从年⽉⽇推出这⼀天是星期⼏呢?
答案是肯定的。
其实我们也常常在这样做。
我们先举⼀个简单的例⼦。
⽐如,知道
了2004年5⽉1⽇是星期六,那么2004年5⽉31⽇“世界⽆烟⽇”是星期⼏就不难推算出
来。
我们可以掰着指头从1⽇数到31⽇,同时数星期,最后可以数出5⽉31⽇是星期⼀。
其实运⽤数学计算,可以不⽤掰指头。
我们知道星期是七天⼀轮回的,所以5⽉1⽇是星
期六,七天之后的5⽉8⽇也是星期六。
在⽇期上,8-1=7,正是7的倍数。
同样,5⽉15
⽇、5⽉22⽇和5⽉29⽇也是星期六,它们的⽇期和5⽉1⽇的差值分别是14、21和28,也
都是7的倍数。
那么5⽉31⽇呢?31-1=30,虽然不是7的倍数,但是31除以7,余数为2,
这就是说,5⽉31⽇的星期,是在5⽉1⽇的星期之后两天。
星期六之后两天正是星期⼀。
这个简单的计算告诉我们计算星期的⼀个基本思路:⾸先,先要知道在想算的⽇⼦
之前的⼀个确定的⽇⼦是星期⼏,拿这⼀天做为推算的标准,也就是相当于⼀个计算的
“原点”。
其次,知道想算的⽇⼦和这个确定的⽇⼦之间相差多少天,⽤7除这个⽇期
的差值,余数就表⽰想算的⽇⼦的星期在确定的⽇⼦的星期之后多少天。
如果余数是
0,就表⽰这两天的星期相同。
显然,如果把这个作为“原点”的⽇⼦选为星期⽇,那
么余数正好就等于星期⼏,这样计算就更⽅便了。
但是直接计算两天之间的天数,还是不免繁琐。
⽐如1982年7⽉29⽇和2004年5⽉
1⽇之间相隔7947天,就不是⼀下⼦能算出来的。
它包括三段时间:⼀,1982年7⽉29
⽇以后这⼀年的剩余天数;⼆,1983-2003这⼆⼗⼀个整年的全部天数;三,从2004年
元旦到5⽉1⽇经过的天数。
第⼆段⽐较好算,它等于21*365+5=7670天,之所以要加
5,是因为这段时间内有5个闰年。
第⼀段和第三段就⽐较⿇烦了,⽐如第三段,需要把
5⽉之前的四个⽉的天数累加起来,再加上⽇期值,即31+29+31+30+1=122天。
同理,第
⼀段需要把7⽉之后的五个⽉的天数累加起来,再加上7⽉剩下的天数,⼀共是155天。
所以总共的相隔天数是122+7670+155=7947天。
仔细想想,如果把“原点”⽇⼦的⽇期选为12⽉31⽇,那么第⼀段时间也就是⼀个
整年,这样⼀来,第⼀段时间和第⼆段时间就可以合并计算,整年的总数正好相当于两
个⽇⼦的年份差值减⼀。
如果进⼀步把“原点”⽇⼦选为公元前1年12⽉31⽇(或者天⽂
学家所使⽤的公元0年12⽉31⽇),这个整年的总数就正好是想算的⽇⼦的年份减⼀。
这
样简化之后,就只须计算两段时间:⼀,这么多整年的总天数;⼆,想算的⽇⼦是这⼀
年的第⼏天。
巧的是,按照公历的年⽉设置,这样反推回去,公元前1年12⽉31⽇正好是
星期⽇,也就是说,这样算出来的总天数除以7的余数正好是星期⼏。
那么现在的问题就
只有⼀个:这么多整年⾥⾯有多少闰年。
这就需要了解公历的置闰规则了。
我们知道,公历的平年是365天,闰年是366天。
置闰的⽅法是能被4整除的年份在
2⽉加⼀天,但能被100整除的不闰,能被400整除的⼜闰。
因此,像1600、2000、2400
年都是闰年,⽽1700、1800、1900、2100年都是平年。
公元前1年,按公历也是闰年。
因此,对于从公元前1年(或公元0年)12⽉31⽇到某⼀⽇⼦的年份Y之间的所有整年
中的闰年数,就等于
[(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400],
[...]表⽰只取整数部分。
第⼀项表⽰需要加上被4整除的年份数,第⼆项表⽰需要去掉
被100整除的年份数,第三项表⽰需要再加上被400整除的年份数。
之所以Y要减⼀,这
样,我们就得到了第⼀个计算某⼀天是星期⼏的公式:
W = (Y-1)*365 + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D.(1)
其中D是这个⽇⼦在这⼀年中的累积天数。
算出来的W就是公元前1年(或公元0年)12⽉
31⽇到这⼀天之间的间隔⽇数。
把W⽤7除,余数是⼏,这⼀天就是星期⼏。
⽐如我们来
算2004年5⽉1⽇:
W = (2004-1)*365 + [(2004-1)/4] - [(2004-1)/100] + [(2004-1)/400] +
(31+29+31+30+1)
= 731702,
731702 / 7 = 104528……6,余数为六,说明这⼀天是星期六。
这和事实是符合的。
2. /* 蔡勒(Zeller)公式计算某⼀天是星期⼏ w:星期;c:(年份前两位);y:年(年份后两位);m:⽉(m⼤
于等于3,⼩于等于14,即在蔡勒公式中,某年的1、2⽉要看作上⼀年的13、14⽉来计算,⽐如2003年1⽉1⽇要看作2002年的13⽉1⽇来计算);d:⽇算出来的W除以7,余数是⼏就是星期⼏。
*/
1#define _CRT_SECURE_NO_WARNINGS
2 #include<stdio.h>
3 #include<stdlib.h>
4int main()
5 {
6int y, c, m, d, w, year, month, day;
7 printf("请输⼊⼀个⽇期:\n");
8 scanf("%d%d%d", &year, &month, &day);
9 y = year % 100;//年 如2015 即年是15年
10 c = year / 100;// 年份前两位 如2015即20
11 m = month; d = day;
12if (m == 1 || m == 2) { //判断⽉份是否为1或2
13 y--;
14 m += 12;//某年的1、2⽉要看作上⼀年的13、14⽉来计算
15 }
16 w = y + y / 4 + c / 4 - 2 * c + 13 * (m + 1) / 5 + d - 1;//蔡勒公式的公式
17while (w < 0) w += 7;//确保余数为正
18 w %= 7;
19 printf("输⼊的⽇期是星期%d", w);
20 system("pause");
21 }。