- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
2016 年全新原创 C 语言实现农历万年历 paradise300
C 语言实现农历万年历
一、前言
我曾经在网上搜索过 C/C++实现的农历万年历,那时,我刚想着要写一款自
己的桌面小工具,希望它包含公、农历转换,节气查询等功能,找到的无非有两
个版本,其中一个写于 2000 年,数据经过压缩,有节气信息,另一个,则是只
有农历,没有节气。而且看到他们使用的数据,都是通过自己的努力,从日历中
收集并整理出来,从 1901 年到 2050 年这 150 年,很是费工夫。
近段时间,当我在整理资料,发现当时的代码时,就又拿起了这两份代码,
总觉得写得不够好,一是它的数据压缩率明显不够大,二是代码效率不够高,于
是决心用自己的方法实现一款全新的农历万年历(源代码见 最后一部分 )。
二、实现方式
1 / 48
2016 年全新原创 C 语言实现农历万年历 paradise300
要实现一个完整的万年历需要具备以下几点内容:
1. 星期
2. 公历每个月总天数
3. 农历正月初一对应的公历日期
4. 农历每个月的总天数
5. 农历闰月
6. 二十四节气
7. 数九、梅雨、三伏
8. 干支
为了表达公历与农历的对应关系,本文引入了“年内序数”这一概念,它指
的是距离公历 1 月 1 日的天数,即 1 月 1 日的年内序数为 0,1 月 2 日的年内序
数为 1,以此类推,由于农历新年滞后于公历元旦,年内序数将被扩展到上一年,
因此会出现负数,这是由于参考点选择不同引起的,比如,要描述上一年的冬至,
则被转化为当前年份的年内序数为-10,表示上一年冬至在今年元旦之前 10 天。
通过对年内序数的使用,就可以使整个对应关系得到简化。
2 / 48
2016 年全新原创 C 语言实现农历万年历 paradise300
星期的计算,普遍采用的公式是:
W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D
Y 是年份,D 是这一天在这一年中的年内序数加 1,也就是这一天在这一年中
是第几天。这个公式验证了一下是可行的。
公历每个月的天数大小还算固定,只要通过判断闰年来区分 2 月天数即可,
还是非常简单的。从第 3 点至第 7 点,这些是没有简单规律的,对于一般需求,
用查表法可以解决,即节省空间,又提升效率,两全齐美。第三部分中将给出详
细数据,以及对数据的解释。
三、数据
为了兼顾空间(数据大小)和时间(运行效率),我也是下足了工夫。
首先,通过对公历正月初一的统计,发现从公元 1600 年到 6400 年之间,最
早出现在 19(即 1 月 20 日),最晚出现在 51(2 月 21 日),两者之差为 32,即
需要 6 个位来描述,6 个位的范围从 0 到 63,足够描述从 19 到 51 了。农历闰月
从正月到十二月,转换为数字即 1 到 12,0 表示无闰月,总的范围是即从 0 到
12,需要 4 个位。而农历月份大小是比较规范,大月 30 天,小月 29 天,因此可
以用 1 个位来表示农历一个月的天数,月份大小信息可以描述为 13 个位。综合
以上几项数据,最为经济的存储方式就是把这几项合在一起,总共 23 位数据,
可以用 3 个字节来存储。简而言之,一个农历年的信息可以用 3 个字节来保存。
农历数据:
第 23 位 第 22 至 17 位 第 16 至 13 位 第 12 至 0 位
保留 农历正月初一的年内序数 闰月 月份大小信息
因此,农历数据使用 24 个位,即 3 字节。
上述四个块,分别有如下含义:
3 / 48
2016 年全新原创 C 语言实现农历万年历 paradise300
① 保留位始终为 0;
② 农历正月初一距离公历元旦的天数;
③ 0 表示无闰月,1 至 12 表示闰月月份;
④ 从低位到高位分别对应从正月到(闰)十二月的每个月的大小,“1”表
示大月,即该月有 30天,“0”表示小月,即该月有 29 天。
以 1900 年为例:
数据:0x3D,0x16,0xD2,
组合起来为:0x3D16D2,
展开为二进制:01111010001011011010010。
二进制位 0 11110 1000 1011011010010
十二月大
十一月小
十月大
九月大
正月初一年内序
闰八月小
数 30
八月大
含义 保留 闰八月 七月大
转为日期为
六月小
1900 年 1 月 31
五月大
日
四月小
三月小
二月大
正月小
有了上述数据,可以轻松得推算出农历某一天的公历日历和公历某一天的农
历日期,转换非常方便。
4 / 48
2016 年全新原创 C 语言实现农历万年历 paradise300
其次,二十四节气那可真是要了我的命了,从
原创力文档


文档评论(0)