关键词不能为空

当前您在: 主页 > 高中公式大全 >

得意忘形的意思:用c++编写计算日期的函数

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2020-11-09 20:51
tags:日期计算天数公式

暖心八字短句小清新-诗杰是谁

2020年11月9日发(作者:包佶)
14.1 分解与抽象
人类解决复杂问题采用的主要策略是“分而治之”,也就是对问题进行 分解,然后分别
解决各个子问题。著名的计算机科学家Parnas认为,巧妙的分解系统可以有效地系 统的状
态空间,降低软件系统的复杂性所带来的影响。对于复杂的软件系统,可以逐个将它分解为
越来越小的组成部分,直至不能分解为止。这样在小的分解层次上,人就很容易理解并实现
了。当所有 小的问题解决完毕,整个大的系统也就解决完毕了。
在分解过程中会分解出很多类似的小问题,他们的 解决方式是一样的,因而可以把这些
小问题,抽象出来,只需要给出一个实现即可,凡是需要用到该问题 时直接使用即可。
案例日期运算
给定日期由年、月、日(三个整数,年的取值在1970- 2050之间)组成,完成以下功
能:
(1)判断给定日期的合法性;
(2)计算两个日期相差的天数;
(3)计算一个日期加上一个整数后对应的日期;
(4)计算一个日期减去一个整数后对应的日期;
(5)计算一个日期是星期几。
针对这个问题,很自然想到本例分解为5个模块,如图14.1所示。
日期计算
判< br>断








日< br>期








计< br>算




图14.1日期计算功能分解图

仔细分析每一个模块的功能的具体流程:
1. 判断给定日期的合法性:
首先判断 给定年份是否位于1970到2050之间。然后判断给定月份是否在1到12之间。
最后判定日的合法 性。判定日的合法性与月份有关,还涉及到闰年问题。当月份为1、3、5、
7、8、10、12时,日 的有效范围为1到31;当月份为4、6、9、11时,日的有效范围为1
到30;当月份为2时,若年 为闰年,日的有效范围为1到29;当月份为2时,若年不为闰
年,日的有效范围为1到28。
准备数据:year、month、day、validity、info
1970≤year≤20 50
True
1≤month≤12
True
month∈{1,3,5,7 ,8,10,12}
True
1≤day≤31
TrueFalseTrue
month∈{4,6,9,11}
False
年为闰年
False
info =“年份不合法”
info=“月份不合
法”
False
False
False
1≤day≤30
TrueFalseTrue
info=
inf o=
“日期
“有效
不合
日期”
法”
info=
in fo=
“日期
“有效
不合
日期”
法”
1≤day≤291≤ day≤28
TrueFalseTrueFalse
info=
“有效
日期 ”
validit
y=Tru
e
info=
“日期
不合法”
validit
y=Fals
e
info=
“有效
日期”
validit
y=Tru
e
info=
“日期
不合
法”
validit
y=Fals
e
输出info
返回va lidity
validity=Falsevalidity=False
validit< br>y=Tru
e
validitvalidit
y=Falsy=Tru
ee
validit
y=Fals
e
图14.2日期合法性判定盒图


判断日期合法性要要用到判断年份是否为闰年,在图14.2中并未给出实现方法,在图14.3中给出。
准备数据:year
year%4==0 && year%100!=0 || year%400==0
True
返回True返回False
False

图14.3闰年判定盒图


2. 计算两个日期相差的天数
计算 日期A(yearA、monthA、dayA)和日期B(yearB、monthB、dayB)相差天数,
假定A小于B并且A和B不在同一年份,很自然想到把天数分成3段:
2.1 A日期到A所在年份12月31日的天数;
2.2 A之后到B之前的整年的天数(A、B相邻年份这部分没有);
2.3 B日期所在年份1月1日到B日期的天数。
整年部分
A日期A日期12月31日
整年 部分B日期1月1日B日期
图14.4日期差分段计算图

若A小于B并且A和B在同一年份,直接在年内计算。
2.1和2.3都是计算年内的一段时 间,并且涉及到闰年问题。2.2计算整年比较容易,但
是也要涉及到闰年问题。这里先不讨论具体流程 ,分析完下面几个模块后再讨论。
3. 计算一个日期加上一个整数天数后对应的日期
计算日期A(yearA、monthA、dayA)加上一个整数天数days对应的日期,
若days小于A日期到A所在年份12月31日的天数

对应结果日期在本年中计算,yearA不变。
否则
yearA加days。
若天数剩下的的部分够整年(闰年问题),则循环
yearA加days;
days去掉一年天数;
对days剩下的不够一年的天数,在该年计算对应日期。
days小于A年内天数days大于A年内天数时,去掉整年到达结果年份
结果日期年
份1 月1日
A日期A日期12月31日
整年部分结果日期

图14.5日期加整数分段计算图

4. 计算一个日期减去一个整数天数后对应的日期
计算日期A(yearA、monthA、dayA)减去一个整数天数days对应的日期,
若days小于A所在年份1月1日到A日期的天数

对应结果日期在本年中计算,yearA不变。
否则
yearA减1。
若days剩下的的部分够整年(闰年问题),则循环
yearA减1;
days去掉一年天数;
对days剩下的不够一年的天数,在该年计算对应日期。
days大于A年内天数时,去掉整年到达结果年份
结果日期12
月31日
days 小于A年内天数
结果日期
整年部分
A日期1月1日A日期

图14.6日期减整数分段计算图


5. 计算一个日期是星期几
计算日期A(yearA、monthA、dayA)为星期几,需要找到一个参照的日期B,只需要
知道日期B为星期几,然后计算出A和B相差的天数,就很容易计算出A为星期几。此处
又需要用到计算 两个日期的差。
通过上述分析,发现到处都在计算一段日期天数,这种一段日期天数分为3种:年内1
月1日到某日期的天数(年内的前半段);年内某日期到12月31日的天数(年内的后半段);
整年的天数。只有整年天数容易计算,其他两种较为复杂,能不能回避呢?
对于日期A和B的差,可 以选定日期C(1970年1月1日),计算C到A的天数CA,
再计算C到B的天数CB,则CB减C A为A到B的天数。而对C到A,只需要计算整年
(因为C为1月1日)加上A的年内前半段,C到B同 理。这样就回避掉了计算年内后半
段的问题。把从选定日期C(1970年1月1日)到某日期A的天数 用函数dateToDays(A)
来描述,有了该函数,则问题2和5都很容易解决了。对于问题3和 4,可以把日期A通过
dateToDays函数转化为天数,再加减一个整数,变成一个新的天数,只 需要再定义一个函数
daysToDate(days)把天数转换为从1970年1月1日经过该天数 对应的日期即可。daysToDate
函数也只需要处理若干整年(因为从1970年1月1日起)和 结果年份内的前半段。
总结一下,本例共抽象出3个公用的函数:
leap:判断闰年函数。
dateToDays:把一个日期转换成从1970年1月1日到该日期的天数。
daysToDate:把天数转换成从1970年1月1日经过该天数所到的日期。
有了这几个函数,解决本例中的问题可以这样做:
模块2. 计算日期A(yearA、mo nthA、dayA)和日期B(yearB、monthB、dayB)相差
天数:
dateToDays(B)- dateToDays(A)
模块3. 计算日期A(yearA、monthA、dayA)加上一个整数天数days对应的日期:
daysToDate (dateToDays(A)+ days)
模块4. 计算日期A(yearA、monthA、dayA)减去一个整数天数days对应的日期:
daysToDate (dateToDays(A)- days)
模块5. 计算日期A(yearA、monthA、dayA)为星期几:
(dateToDays(A)+Offset-2)%7+1
Offset是1970年1月1日星期值,值为4。
dateToDays函数用来计算1 970年1月1日到A(yearA、monthA、dayA)的天数,结
果存放在sum中。二维数 组m的0行和1行分别存放闰年和平年每个月的天数。计算过程
分为3部分:
(1) 197 0年到yearA-1年循环,把每年的天数累加到sum中。注意,闰年时leap返
回1,古润年时 多加一天。
(2)在yearA年份,从1月到monthA-1月循环,把每月的天数累加到sum 中。注意,
闰年时,每月天数在数组m的0行中,平年时,每月天数在数组m的1行中。
(3)把dayA累加到sum中。
例如对日期1972年2月5日。第一步把从1970年 到1971每年的天数累加到sum中,
sum的值为730;第二步把从1972年1月到1972年 1月每月的天数累加到sum中,sum的
值为761;第三步把5日累加到sum中,sum的值为7 66。详细流程如盒图14.7所示。
准备数据:
A(yearA、 monthA、 dayA ); sum=0; i=1970;
m[2][12]={{31,29,31,30,3 1,30,31,31,30,31,30,31},
{31,28,31,30,31,30,31,31,30,31,30,31}};
isum=sum+365+leap(i)
i++
i=0
Tr ue
ileap(yearA)
False
isum=sum+m[0][i]
i++
sum=sum+m[ 1][i]
i++
sum=sum+dayA
返回sum

图14.7日期转换为天数NS盒图

daysToDate函数用来计算从197 0年1月1日起经过days天后对应的日期A(yearA、
monthA、dayA)。二维数组m 的0行和1行分别存放闰年和平年每个月的天数。计算过程
分为3部分:
(1)结果年份ye arA的计算,yearA初值为1970,当days大于yearA年的天数时循环:
在days中 减去yearA的天数,并且把yearA增加1。其中,yearA的天数要考虑闰年问题。
(2) 结果月份monthA的计算,monthA初值为1,此时days已经小于yearA年的天数。
d ays大于monthA月的天数时循环:在days中减去monthA月的天数,并且把monthA增加< br>1。其中,闰年时,每月天数在数组m的0行中,平年时,每月天数在数组m的1行中。
(3) 结果日dayA的计算,此时days已经小于yearA年month月的天数。dayA的值即
为d ays。
例如把天数days(766)转为日期,yearA的初值为1970,monthA的初值为1。
第一步,days减去1970年的365天days变为401,yearA变为1971;days 再减去1971
年的365天days变为36,yearA变为1972;此时days的36不够1 972年的天数,故年份结
果为1972。
第二步,days减去1972年1月的31天d ays变为5,monthA变为2;此时days的5不
够1972年2月的天数,故月份结果为2。
第三步,日的值即为day,也就是dayA的值为5。
详细流程如盒图14.8所示。
准备数据:
days;yearA=1970;monthA=1;dayA=1; m[2][12]={{31,29,31,30,31,30,31,31,30,31,30,31},
{31,28,31,30,31,30,31,31,30,31,30,31}};
days>leap(yearA)+365
days=days-(leap(yearA)+365 )
yearA++
True
leap(yearA)
False
m[ 0][monthA-1]days=days-
m[0][monthA-1]< br>monthA++
dayA=days
返回日期 yearA、monthA、dayA
m[1][monthA-1]days=days-
m[1][mont hA-1]
monthA++

图14.8天数转换为日期NS盒图

信息管理与信息系统-庸才是什么意思


真理的反义词-八下地理思维导图


discuss名词-江苏高考报名网址


lie的ing形式-福建华南女子职业学院


哪个专业就业前景好-报答老师的诗句


适合幼儿看的电影-宋江的性格


潍坊科技学院是几本-抗疫故事作文


言必行行必果的意思-儿童心理特点



本文更新与2020-11-09 20:51,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/441525.html

用c++编写计算日期的函数的相关文章