万年历算法的实现

2019-04-22 22:11

/*

* cal.c *

* Created on: Apr 10, 2011 * Author: Administrator *

* 现行的格里历是从儒略历演化而来的。儒略历每4年一个润年,润年366天,平年365天。

* 如果从公元1年算的话,那么凡是能够被4整除的都是润年。从天文角度看,儒略历这种

* 历法是有误差的,到16世纪误差已经达到了10天。1582年,罗马教皇对儒略历进行了

* 一次校定,该年的10-5到10-14这10天被抹掉,并规定凡不能被400整除的世纪年不再

* 算为润年,校定之后的儒略历即为现行的格里历。 *

* 但是英国直到1752年才开始使用格里历,此时时间误差已经达到了11天,原因是1700

* 年在儒略历中是润年,而在格里历中是平年。1752年英国议会决定将本年的9-3到9-13

* 这11天抹掉,以同步格里历。当时美国不是英国的殖民地,所以在美国的日历中也是没有

* 1752-9-3到1752-9-13这11天的。 我们知道UNIX系统源于美国,Linux系统源于UNIX,

* 这就是为什么当我们在Linux系统中敲\这条命令时,会看到一个只有19天

* 的9月。 *

* 以上内容参考自维基百科 *

* 本程序模似Linux中cal命令的部分功能。允许输入的年分为1...9999。 * 编译器:gcc V4.5.0 *

* 分析:

* 1752年是特殊年,1752-9月是特殊年中的特殊月。 *

* 1752-9-2之前,采用的是儒略历,凡能被4整除都为润年;1752-9-14之后,采用的是

* 格里历,不能被400整除的世纪年不再作为润年。 *

* 格里历闰年计算方法 * 世纪年 ***4000的倍数 **3200/1900的倍数 400的倍数 100的倍数 4的倍数

* 结果 不闰 不闰 闰 不闰 闰 * 注:

* 3200/1900的倍数是天文科学家研究出来

* 增加4000的倍数不闰更准确,但目前只是世纪年还不足4000,因此尚未用途 *

* 格里历在400年的周期中有146,097天,恰好是20,871 星期。所以,例如,格里历七年、

* 407年、807年、1207年、1607年、2007年的日期与星期是完全相同的。也就是说,格里

* 历每400年一个周期。 *

* 公元1-1-1,按儒略历是周六,按格里历是周一;因1752-9-2之前采用的都是儒略历,所以

* 公元1-1-1应该是周六。 * 1752-9-14是周四。 *

* 公元1-1-1到1752-9-2,日期是连续的,儒略历;公元1752-9-14至今,日期是连续的,格里历。 *

* 对于给定的一个 年(Y)-月(M)-日(D) ,则从公元1-1-1到 给定的日期的天数为:

* 1752-9-2前:365*(Y-1)+(Y-1)/4+e,其中e表示从Y-1-1到Y-M-D的天数,

* 且这天是该周的第((Y-1)+(Y-1)/4+5+e)%7天。 *

* 1752-9-14后:365*(Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e, * 且这天是该周的第((Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e)%7天。

*

* 需要注意的是,从1-1-1到1752-9-14之后的某个日期的天数并非实际的天数,它只是根据格里历的

* 的规则推算出来的,目的也只是为了得到日期与星期的对应。 *

* 算法思想:

* 对于年历,若能知道本年的1月1日是周几,也就知道了本年的年历分布。 * 对于月历,若能知道本月的1日是周几,也就知道了本月的月历分布。 * 所以关键是正确的推算出给定的一个日期是星期几。以下为推算方法: * 1752-9-2之前:((Y-1)+(Y-1)/4+5+e)%7

* 1752-9-14之后:((Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e)%7 * 把1800-2199年当成一个周期,对于其后的日期,只需在1800-2199之间找到

* 对应的日期,就可以知道是星期几,这样就不用再考虑4000年之后4000的倍数

* 不是润年这种情况。 (Y-1800)@0+1800 * *

* */

#include #include #include void PrintHelp(); int* CurrentCal();

int CheckYear(int year); int CheckMonth(int month);

int CheckDay(int year, int month, int day); int IsNum(char *argv);

int IsLegalParameter(int argc, char **argv); long StrToLong(char *argv);

long Power(int baseNumber, int exponent); void PrintCalendar(int year);

void PrintCommonCalendar(int year, int row); void PrintOneQuarter(int year, int mfOfWeek, int mfDays, int msOfWeek, int msDays, int mtOfWeek, int mtDays, int row); void Print1752_3Quarter();

void PrintMonthlyCalendar(int year, int month); void PrintMonthName(char *, int year);

void PrintCommonMonthlyCalendar(int dayOfWeek, int days); void PrintDayOfWeek(int year, int month, int day); int DayOfWeek(int year, int month, int day); int CurrentDays(int year, int month, int day);

int a;//输入的年这个参数的字符串长度,主根用于后面的PrintMonthName(char *, int)函数

int main(int argc, char **argv) { int year, month, day;

int flag = IsLegalParameter(argc, argv); switch (flag) { case -1:

printf(\); PrintHelp(); break; case 0:

PrintMonthlyCalendar(*(CurrentCal()), *(CurrentCal() + 1)); break; case 1: {

a = strlen(*(argv + 1)); switch (argc) { case 2:

year = StrToLong(*(argv + 1)); if (!CheckYear(year)) { break; }

printf(\, year); PrintCalendar(year); break; case 3:

year = StrToLong(*(argv + 1)); if (!CheckYear(year)) { break;

}

month = StrToLong(*(argv + 2)); month = StrToLong(*(argv + 2)); if (!CheckMonth(month)) { break; }

PrintMonthlyCalendar(year, month); break; case 4:

year = StrToLong(*(argv + 1)); if (!CheckYear(year)) { break; }

month = StrToLong(*(argv + 2)); if (!CheckMonth(month)) { break; }

day = StrToLong(*(argv + 3));

if (!CheckDay(year, month, day)) { break; }

PrintDayOfWeek(year, month, day); break; default:

year = StrToLong(*(argv + 1)); if (!CheckYear(year)) { break; }

month = StrToLong(*(argv + 2)); if (!CheckMonth(month)) { break; }

day = StrToLong(*(argv + 3));

if (!CheckDay(year, month, day)) { break; }

PrintDayOfWeek(year, month, day); break; } }

default: break; }

return 0; }

void PrintHelp() {

printf(\:cal [ [ []]\); }

int CheckYear(int year) {

if (year == 0 || year > 9999) {

printf(\, year); return 0; }

return 1; }

int CheckMonth(int month) {

if (month < 1 || month > 12) {

printf(\, month); return 0; }

return 1; }

int CheckDay(int year, int month, int day) { switch (month) { case 1:

if (day < 1 || day > 31) {

printf(\, day); return 0; }

return 1; break; case 2:

if ((year < 1753 && year % 4 == 0) || ((year % 4 == 0 && year % 100

!= 0) || year % 400 == 0)) { if (day < 1 || day > 29) {

printf(\, day); return 0; } }

if (day < 1 || day > 28) {

printf(\, day); return 0; }

return 1; break; case 3:

if (day < 1 || day > 31) {

printf(\, day); return 0; }

return 1; break; case 4:

if (day < 1 || day > 30) {

printf(\, day); return 0; }

return 1; break; case 5:


万年历算法的实现.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:珠海农用无人机统防统治植保作业工作方案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: