前言 這篇博客主要是參考網上的一個帖子,然後自己推斷驗證,在原創和轉載之間猶豫了很久,鑒於我確實做了很多推導工作,姑且就認為我是原創吧! 簡介星期制度 星期制度是一種古老的制度。據說因為《聖經×創世紀》中規定上帝用六天的時間創世紀,第七天休息,所以人們也就以七天為一個周期來安排自己的工作和生活,而星期天是休息日。 求星期幾的思路 原點差值取余法 首先,先要知道在想算的日子之前的一個確定的日子是星期幾,拿這一天作為推算的標准,也就是相當於一個計算的“原點”。其次,知道想算的日子和這個確定的日子之間相差了多少天,用7除以這個日期的差值,余數就是想算的日子的星期在確定的日子的星期之後的多少天。如果余數是0,就表示這兩天的星期相同。顯然,如果把這個作為“原點”的日子選為星期日,那麼余數正好就是星期幾。 “原點”選取 直接計算兩個日期之間的天數,還是不免繁瑣。比如1982年7月29日和2004年5月1日之間相隔794天,這不是一下子就能計算出來的,它包括了三個時間段: 1982年7月29日以後這一年的剩余天數 1983年-2003年這21個整年的全部天數 從2004年1月1日到2004年5月1日的經過的天數 為了簡化日期的計算,可以考慮減少第一部分的天數計算,因此考慮可以把原點日期選取為公元前1年12月31日(ps:恰好這天就是周日)。這樣的話,第一段時間為0,第二段時間的整年數為想計算日期所在的年數減一(ps:計算多少天注意考慮閏年)。第三段日期正常計算即可。 公歷的置閏規則 公歷的平年是365天,閏年是366天。置閏的方法是能被4整除的年份在2月加一天,但能被100整除的不閏,能被400整除的又閏。符合規則公式可以是(c語言描述): [cpp] if( (year % 4 == 0 && year % 100 != 0) || )year % 400 == 0)) 第一個星期幾計算公式 對於從公元前1年(或者說公元0年)12月31日到某一日子的年份Y之間的所有整年中的閏年數,就等於 [cpp] runnian = [(Y - 1) / 4] - [(Y - 1) / 100] + [(Y - 1) / 400] []表示取整,第一項表示需要加上所有被4整除的年份數,第二項表示需要減掉被100整除的年份數,第三項表示需要再加上被400整除的年份數。 這樣我們就得到了第一個計算某一天是星期幾的公式 : [cpp] w = (Y - 1) * 365 + [(Y - 1) / 4] - [(Y - 1) / 100] + [(Y - 1) / 400] + D 其中D是這個日子在這一年中累積的天數。 簡化計算公式 間隔天數w的作用僅僅是為了得到它除以7之後的余數,這就可以啟發我們是不是可以簡化這個w值,只要找一個和它余數相同的較小的數來代替,用數輪上的術語來說,就是找一個和它同余的較小的正整數,照樣可以計算出准確的星期數。 顯然,w這麼大的原因是因為公式的第一項(Y - 1) * 365太大了,可以這樣化減: [html] (Y - 1) * 365 = (Y - 1) * (364 - 1) = (Y - 1) * (7 * 52 + 1) = 52 * (Y - 1) * 7 + (Y - 1) 結果中的第一項是7的倍數,除以7余數為0,因此(Y - 1) * 365 可以被(Y - 1)代替。 簡化後的計算星期幾的公式為: [cpp] w = (Y - 1)+ [(Y - 1) / 4] - [(Y - 1) / 100] + [(Y - 1) / 400] + D 九度acm求星期幾 題目 [html] 題目描述: We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400. For example, years 2004, 2180 and 2400 are leap. Years 2004, 2181 and 2300 are not leap. Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating. 輸入: There is one single line contains the day number d, month name M and year number y(1000≤y≤3000). The month name is the corresponding English name starting from the capital letter. 輸出: Output a single line with the English name of the day of week corresponding to the date, starting from the capital letter. All other letters must be in lower case. 樣例輸入: 9 October 2001 14 October 2001 樣例輸出: Tuesday Sunday 提示: Month and Week name in Input/Output: January, February, March, April, May, June, July, August, September, October, November, December Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ac代碼(c語言) [cpp] #include <stdio.h> #include <stdlib.h> #include <string.h> struct date { int day; char month[12]; int year; }; int strToMonth(char *); void printWeek(int, int, int); int main() { struct date today; int count, m; while(scanf("%d %s %d", &today.day, today.month, &today.year) != EOF) { m = strToMonth(today.month); printWeek(today.day, m, today.year); } return 0; } void printWeek(int day, int month, int year) { int number, week, i; int m[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; if((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) { m[1] = 29; } number = (year - 1) + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400; for(i = 0; i < month - 1; i ++) { number += m[i]; } number += day; week = number % 7; switch(week) { case 0: printf("Sunday\n"); break; case 1: printf("Monday\n"); break; case 2: printf("Tuesday\n"); break; case 3: printf("Wednesday\n"); break; case 4: printf("Thursday\n"); break; case 5: printf("Friday\n"); break; case 6: printf("Saturday\n"); break; } } int strToMonth(char *month) { if(strcmp(month, "January") == 0) { return 1; }else if(strcmp(month, "February") == 0) { return 2; }else if(strcmp(month, "March") == 0) { return 3; }else if(strcmp(month, "April") == 0) { return 4; }else if(strcmp(month, "May") == 0) { return 5; }else if(strcmp(month, "June") == 0) { return 6; }else if(strcmp(month, "July") == 0) { return 7; }else if(strcmp(month, "August") == 0) { return 8; }else if(strcmp(month, "September") == 0) { return 9; }else if(strcmp(month, "October") == 0) { return 10; }else if(strcmp(month, "November") == 0) { return 11; }else if(strcmp(month, "December") == 0) { return 12; } }