民间实用万年历.docx
- 文档编号:3450334
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:21
- 大小:43.56KB
民间实用万年历.docx
《民间实用万年历.docx》由会员分享,可在线阅读,更多相关《民间实用万年历.docx(21页珍藏版)》请在冰豆网上搜索。
民间实用万年历
民间实用万年历
万年历算法研究及实现第5卷第4期中国水运Vol.5No.42007年4月ChinaWaterTransportApril2007万年历算法研究及实现张剑锋陈慕君摘要:
万年历是一个经典的算法问题,在教学过程中可以作为实例进行分析讲解,具有较高的学习分析价值,也具有一定的实用价值,结合不同的方法,本文有一个系统全面的介绍。
关键词:
万年历算法阴历阳历闰年中图分类号:
TP29文献标识码:
A文章编号:
1006-7973(2007)04-0143-02万年历是一个古老而又经典的算法问题,已经有不少的实现方法,但是都多少会存在一些问题和不足,在这里对此算法做一个系统的分析与介绍,先撇去农历与公历之间的转化,只做公历与星期的讨论。
注意这样一个事实:
从公元元年一月一日开始到现在,每一天都是连续的,而每个星期有七天,也是连续的,也就是说日期和星期是一对一的,没有断档现象。
基本思想是:
计算出当前天是从公元元年一月一日开始的第几天,再利用星期的周期性来计算公元任何一天是星期几。
假设当前年份为y,并忽略闰年,则从公元元年一月一日到y-1年共有365*(y-1)天,加上闰年多出来的天数,即加上1*((y-1)/4-(y-1)/100+(y-1)/400),得365*(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)。
我们再补上从当前1月1日开始到当前天的天数e,即为所求。
即365*(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)+e。
它的值即为当前天是从公元元年一月一日开始算起的第几天。
补上一个x(x是与公元元年一月一日是星期几有关的一个0~6的整数),并将这个表达式赋给变量t,即:
t=x+365*(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)+e,再用t除以7,余几即为星期几(余0为星期日)。
下面讨论x的求法,如果知道公元元年一月一日是星期几,就可以直接得到x的值,但现在公式还没有求出来,不知道公元元年一月一日是星期几。
不过没关系,毕竟知道最近的日期是星期几。
不妨看一下2001年1月1日是星期几,结果是星期一,代入公式得t=x+730516,用730516除以7,得104355,余数是1,则为了保证2001年1月1日是星期一,取x为0,所以公元元年一月一日也是星期一。
至此,得到了完整的公式:
t=365*(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)+e,再将它做一下改进,我们将公式变形为:
t=(52*7+1)*(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)+e,利用星期的周期性,将52*7+1从公式中删除为:
t=(y-1)+((y-1)/4-(y-1)/100+(y-1)/400)+e,T"};voidmain(){intd,m,y,e,t,f;printf("INPUTTHEDAY:
");scanf("%d",&d);printf("INPUTTHEMONTH:
");scanf("%d",&m);printf("INPUTTHEYEAR:
");scanf("%d",&y);switch(m){case1:
e=d;break;case2:
e=31+d;break;case3:
e=59+d;break;case4:
e=90+d;break;case5:
e=120+d;break;case6:
e=151+d;break;case7:
e=181+d;break;case8:
e=212+d;break;case9:
e=243+d;break;case10:
e=273+d;break;case11:
e=304+d;break;case12:
e=334+d;break;default:
return;}if(y%4==0&&y%100!
=0||y%400==0)if(m>2)++e;--y;以下是这种算法的C语言程序:
#includechar*name[]={"SUN","MON","THU","WED","THU","FRI","SA收稿日期:
2007-3-20作者简介:
张剑锋男(1981-)河南农业职业学院教师(451450)研究方向:
计算机科学技术144中国水运第5卷t=y+y/4-y/100+y/400+e;f=t%7;printf("TODAYIS%sn",name[f]);}到此,似乎是问题基本都解决了。
我们先不说这个算法本身,我们再来了解一下历法的知识。
国际上使用的历法有几十种,其中最主要的有公历、回历和佛历,即所谓三大历法。
不管是哪种历法,无非是对年月日的安排。
这些安排主要依据天体的运动。
西方历法的第一次改革是罗马朱利乌斯·凯撒大帝引进的。
他采用的四年一闰的闰年方式。
由于一个太阳年不刚好是365.25天,而是365.242199…天。
到16世纪,每年11分14秒的误差已经累积成10天,也就是历法上多了10天。
于是教皇格利戈里八世进行了一次校正。
他在1582年2月24日以教皇训令颁布,将1582年10月5日至14日抹掉,并且对原来的闰年方法进行了校正。
经过校正的历法叫格利戈里历法,也就是我们现在用的公历。
1752年,英国人决定采用格利戈里历法,不过从1582年到那时,历法又多出了1天,所以英国议会在1752年作出决定,抹掉11天—1752年9月3日至13日。
这是怎么搞的,我们不是说过这样一个事实:
从公元元年一月一日开始到现在,每一天都是连续的,而每个星期有七天,也是连续的,也就是说日期和星期是一对一的,没有断档现象。
现在居然又出现了特殊状况,我们以前的算法都是错的。
不过一个简单的方法就可以证明确实存在着断档—用Linux的cal命令。
启动你的Linux在#提示符下输入cal91752你会看到:
September1752SuMoTuWeThFrSa121415161718192021222324252627282930有趣吧一个只有19天的九月。
那我们的算法也要跟着要大变身了。
不用着急,我们分析一下当前的情况:
就是在原来的算法的基础上,出现了一个比较特殊的1752年,我们的就针对这个特殊的地方进行局部的调整,看看有什么可以办法解决这个问题。
不妨作如下演算:
为了一致起见,采用一、二月作为上年的十三、十四月。
采用查表的方法建表,并对7取模(表一),再建立函数值表(表二),很显然二者是相同的。
三月00四月313五月615六月921七月1223八月1536三月0四月3五月5六月1七月3八月6T"};voidmain(){intD,M,Y,A;printf("Day:
");scanf("%d",&D);printf("Month:
");scanf("%d",&M);printf("Year:
");scanf("%d",&Y);if((M==1)||(M==2)){/*一月、二月当作前一年的十三、十四月*/M+=12;Y--;}if((Y 第二:
加了一个if分支,简单易懂,直观有效,且效率并不差。
好了,该解决这个历史遗留问题了。
其实,并没有什么数学公式能算出指定日期是星期几,我们可以试着拼凑一个,不过何必呢?
加个if分支不就解决问题了吗?
下面就可得到突破1752年9月14日日期限制的C语言程序。
/*假设输入的是正确的日期*/#includechar*name[]={"SUN","MON","THU","WED","THU","FRI","SA程序设计工程实训报告万年历系统仲恺农业工程学院课程设计报告编写一万年历系统课程名称C语言程序设计工程训练及编程比赛姓名Angus院(系)信息科学与技术学院专业班级计算机科学与技术XXX班学号201320244225指导教师石玉强仲恺农业工程学院教务处制二O一四年六月目录1需求分析.....................................................................................................................................................12系统总框图和功能模块说明.....................................................................................................................12.1系统界面图...................................................................................................................................12.2功能模块说明..................................................................................................................................13系统设计...................................................................................................................................................13.2主要功能函数.....................................................................................................................................23.3关键函数的流程图............................................................................................................................24系统调试.....................................................................................................................................................445总结...........................................................................................................................................................4源程序清单...............................................................................................................................................5运行环境:
电脑型号技嘉台式电脑操作系统Windows7旗舰版64位SP1(DirectX11)处理器英特尔Xeon(至强)E3-1230V2@3.30GHz四核主板技嘉B75M-D3V(英特尔IvyBridge-B75Express芯片组)内存8GB(威刚DDR31600MHz)主硬盘希捷ST500DM002-1BD142(500GB/7200转/分)显卡ATIRadeonHD7750Series(1GB/迪兰恒进)显示器LGGSM4B6FW1942(19.1英寸)声卡瑞昱ALC887@英特尔PantherPointHighDefinitionAudioController网卡瑞昱RTL8168EPCI-EGigabitEthernetNIC/技嘉编程环境:
MicrosoftVisualStudioUltimate20131需求分析要求:
模仿现实生活中的挂历。
当前页以系统当前日期的月份为准显示当前月的每一天(显示出日及对应的星期几)。
当系统日期变到下一月时,系统自动翻页到下一月。
还是适当添加实时时间显示的功能。
2系统总框图和功能模块说明2.1系统界面图**显示程序信息**显示当前年月日显示当月的日期表**实时显示当时时间**界面设计图2.2功能模块说明打开程序,程序会自动获取系统当前的时间并将系统返回的时间格式进行转换,转换后的年月日格式通过函数绘制出当月的日期表,最后将时间格式一同显示。
最后使用函数让整体自动刷新。
即可实现实时显示时间日期的功能。
3系统设计#include标准输出输入头文件#includeSleep函数的头文件,控制循环的停顿#includetime函数头文件,获取及处理系统时间所用#includestrlen,strtok,strcpy等函数的头文件,进行对字符串和字符的处理。
#includeatoi函数的头文件,可以将数组字符串转换为数值。
#includesystem函数头文件,可以改变背景及前景颜色,清除屏幕等功能3.2主要功能函数daysofmonth(intyear,intmonth)自定义函数daysofmonth(year,month)通过输入年份year和月份month来计算某年某月的天数。
分别有4种情况(28,29,30,31)共4种返回值,通过返回值来确定一个月的天数。
cvrt2num(char*diff)自定义函数cvrt2num(diff)(Convert2number),由于通过系统获取的时间包含字符串,在处理过程中比较麻烦,故用此函数来进行对比,将输入的月份转换成数字形式让操作更简便。
3.3关键函数的流程图Daysofmonth函数流程图:
cvrt2num(char*diff)函数流程图:
4系统调试4总结1.字符串的处理问题。
通过上网查阅资料找到获取系统时间的方法,不过获得的时间是一段长字符串,其中使用空格隔开,输出格式为*weekmonthdaytimeyearn*,通过使用strtok函数,以输出格式的空格为标示符,将字符串进行分割并存储到二维数组中。
其中最后一组year字符串中的最后一个字符多出了一个换行符n,通过string[strlen(string)-1]=0来消除字符串中最后一个字符。
最终获得*week*n*month*n*day*n*time*n*year*,进行输出显示后结果均正确存储。
2.字符串的转换问题。
从系统获取的时间均用字符串进行存储。
处理很不方便,所以需要转换为容易使用和识别的形式。
其中将年份字符串使用atoi函数转换为了数值。
从系统获取的时间中月份的表示形式为三位月份英文缩写。
加大了转换的难度。
所以新建立了cvrt2num函数来对面系统输出的月份,在通过字符串对比函数strcmp(string1,string2),将月份转换为数值。
3.日历月份天数的处理问题。
建立新函数daysofmonth(year,month)判断不同月份的天数,同时也要考虑到闰年和平年的情况,将4种情况以4个返回值输出以简化算法步骤。
.4.日期星期对号问题。
通过公式a=(year+(year-1)/4-(year-1)/100+(year-1)/400)%7;可以算得年份的第一个月第一天所对应的星期。
不过由于题目要求只输出当前月份的日期表,所以就要计算到当前月份第一天所对应的星期,需要从当前年份第一月第一天推算到当前月份第一天,建立的循环中数据的相互影响很大,程序经常出错,所以建立了多个显示函数来检查数据的变动,反复调整循序渐进最终终于得到了正确的答案。
5.界面调整,由于控制台程序界面一般都比较简单,所以显示很单一,适当对界面进行排版增加观赏性。
5源程序清单#include#include#include#include#include#includeintdaysofmonth(intyear,intmonth)//定义一个函数来判断月份的天数{if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)return
(1);//returnvalueif(year%4!
=0||year%100==0&&year%400!
=0)return
(2);//returnvalueelsereturn(4);//returnvalueintcvrt2num(char*diff)//defineafunctioninordertoconverttheformatofthemonth.{charmonths[12][4]={for(t=0;t7){a=k%7;}k=a;//printf(char**p;char*week[]={printf(printf(printf(printf(for(j=0;j 随着社会、科技的发展,人类得知时间,从观太阳、摆钟到现在电子钟,不断研究、创新。
为了在观测时间的同时能够了解其他与人类密切相关的信息,比如温度、星期、日期等,电子万年历诞生了,它集时间、日期、星期和于一身,具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
该电子万年历主要采用AT89S52单片机作为主控核心,由DS1302时钟芯片提供时钟、LCD动态扫描显示屏显示,AT89S52单片机具有功耗小,片内ROM全都采用FlashROM:
能以3V的超低电压工作,同时也与MCS-51系列单片机完全兼容,该芯片内部存储器为8KBROM存储空间,同时具有89C51的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或程序的新增功能需要烧入程序时,不需要对芯片进行多次插拔,所以不会对芯片造成损坏。
DS1302时钟芯片是美国DALLAS公司推出的具有涓流电流充电功能的低功耗实时时钟芯片,它可以对年、月、日等进行计时,还有闰年补偿等功能,而且使用寿命长,误差小,数字显示是采用的LCD液晶显示,可以同时显示各种需要的信息。
此外,该电子万年历还具有时间校准等功能。
目录1绪论....................................................................11.1选题背景.............................................................11.2选题目的...........................................................11.3设计意义.............................................................22设计要求与方案论证.......................................................32.1设计要求...........................................................32.2系统基本方案选择和论证.............................................32.2.1单片机芯片的选择和方案论证.....................................32.2.2显示模块选择方案和论证.........................................32.2.3时钟芯片的选择方案和论证.......................................32.2.4温度传感器的选择方案与论证.....................................42.3最终方案确定.........................................................43系统的硬件设计与实现.....................................................53.1系统硬件概述........................................................53.1.1系统设计框图...................................................53.1.2系统硬件需求介绍...............................................53.2系统硬件各模块作用..................................................63.2.1控制系统的设计.................................................63.2.2时钟电路模块的设计.............................................63.2.3温度采集模块设计..............................................83.2.4闹钟(蜂鸣器电路模块).........................................93.2.5按键部分.......................................................93.2.6液晶显示模块概述..............................................103.2.7USB和外部电源供电电路........................................1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 民间 实用 万年历