### 万年历星期的算法(C语言) #### 知识点概述 本篇文章将深入解析一个用C语言编写的万年历星期计算程序,该程序能够准确计算从公元0000年至9999年间的任何一天是星期几。算法主要通过一系列数学运算和逻辑判断来实现对日期的星期计算。 #### 代码解析与知识点详解 ##### 1. 月份天数表 (WeekTab) 首先定义了一个数组 `WeekTab` 来存储每个月的天数。这个数组的每个元素由两部分组成:高位表示星期几的偏移量(`week`),低位表示该月的天数(`day`)。 ```c unsigned char WeekTab[] = { (3 << 5) + 31, // 1月 (6 << 5) + 29, // 2月 (0 << 5) + 31, // 3月 (3 << 5) + 30, // 4月 (5 << 5) + 31, // 5月 (1 << 5) + 30, // 6月 (3 << 5) + 31, // 7月 (6 << 5) + 31, // 8月 (1 << 5) + 30, // 9月 (4 << 5) + 31, // 10月 (0 << 5) + 30, // 11月 (2 << 5) + 31 // 12月 }; ``` 这里使用了位操作 `(x << 5)` 将星期的偏移量左移五位,然后加上对应的天数。例如,1月的天数为31天,而它的星期偏移量为3,所以第一个元素的值为 `(3 << 5) + 31`。 ##### 2. 计算2000-2099年的星期几 (WeekDay20) 此函数用于计算2000至2099年之间的任意日期是星期几: ```c unsigned char WeekDay20(unsigned char y, unsigned char m, unsigned char d) { unsigned char week, day; day = WeekTab[m - 1]; week = day >> 5; day &= 0x1f; if ((m < 3) && (y & 0x03)) { if (m == 2) day--; week++; } y = y + (y >> 2); week = (week + y + d + 2) % 7; return (week << 5) | day; } ``` - **参数**: - `y`:年份的最后两位。 - `m`:月份。 - `d`:日期。 - **计算过程**: 1. 从 `WeekTab` 数组获取当前月份的天数和星期偏移量。 2. 如果是1月或2月,并且当前年份是闰年,则减去一天。 3. 计算年份的闰年修正值:`y + (y >> 2)`。 4. 计算星期几:`(week + y + d + 2) % 7`。 ##### 3. 计算0000-9999年的星期几 (WeekDay) 对于更广泛的日期范围,需要使用不同的公式进行计算: ```c unsigned char WeekDay(unsigned char c, unsigned char y, unsigned char m, unsigned char d) { unsigned char week, day; c &= 0x03; c = c | (c << 2); day = WeekTab[m - 1]; week = day >> 5; day &= 0x1f; if ((m < 3) && !((c == 0) || (y & ((y & 0x03) == 0)))) { if (m == 2) day--; week++; } y = y + (y >> 2); week = (week + c + y + d + 2) % 7; return (week << 5) | day; } ``` - **参数**: - `c`:世纪号。 - `y`:年份的最后两位。 - `m`:月份。 - `d`:日期。 - **计算过程**: 1. 获取世纪号的模4值,并进行相应的位操作。 2. 使用与 `WeekDay20` 类似的方法来计算星期几,但考虑到了世纪的影响。 ##### 4. BCD转十进制 (BcdToBin) 为了处理输入数据,这里还提供了一个辅助函数 `BcdToBin` 用于将BCD编码转换为十进制数: ```c unsigned char BcdToBin(unsigned char val) { val = (val >> 4) * 10 + (val & 0x0f); return val; } ``` - **功能**:将输入的BCD编码转换为十进制数值。 ##### 5. 主函数示例 (main) 在主函数 `main` 中演示了如何使用上述函数计算两个特定日期的星期几: ```c void main(void) { unsigned char c, y, m, d; unsigned char cx, yx, mx, dx; unsigned char WDay, Week, Day; // 示例1: 0001年1月1日 c = 0x00; y = 0x01; m = 0x01; d = 0x01; cx = BcdToBin(c); yx = BcdToBin(y); mx = BcdToBin(m); dx = BcdToBin(d); WDay = WeekDay(cx, yx, mx, dx); Week = WDay >> 5; Day = WDay & 0x1f; // 示例2: 1918年1月21日 c = 0x19; y = 0x18; m = 0x01; d = 0x21; cx = BcdToBin(c); yx = BcdToBin(y); mx = BcdToBin(m); dx = BcdToBin(d); WDay = WeekDay(cx, yx, mx, dx); Week = WDay >> 5; Day = WDay & 0x1f; } ``` - **执行流程**: 1. 定义变量。 2. 对示例日期进行BCD到十进制的转换。 3. 调用 `WeekDay` 函数计算星期几。 4. 分离星期和日期信息。 通过以上分析,我们可以看出该程序通过巧妙地运用位操作、数学运算以及条件判断,成功实现了从0000年至9999年间任意日期星期几的计算。这对于编写日期相关的应用程序具有重要的参考价值。
#include <stdio.h>
code unsigned char WeekTab[] = {//闰年月星期表
(3 << 5) + 31,//1月
(6 << 5) + 29,//2月
(0 << 5) + 31,//3月
(3 << 5) + 30,//4月
(5 << 5) + 31,//5月
(1 << 5) + 30,//6月
(3 << 5) + 31,//7月
(6 << 5) + 31,//8月
(1 << 5) + 30,//9月
(4 << 5) + 31,//10月
(0 << 5) + 30,//11月
(2 << 5) + 31 //12月
};
/*------------------------------------------------------------------------------
----------
2000年~2099年星期算法
--------------------------------------------------------------------------------
---------*/
unsigned char WeekDay20(unsigned char y, unsigned char m, unsigned char d)
{
unsigned char week, day;
day = WeekTab[m - 1];//月表
week = day >> 5;//月星期数
day &= 0x1f;//月天数
- 粉丝: 1
- 资源: 10
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C#ASP.NET工程项目管理源码带文档数据库 SQL2008源码类型 WebForm
- 20210203047_卢诗贝_大数据1班.rar
- GL《装成偏执狂攻略清冷师尊翻车后》作者:酸辣离蒿.txt
- C#会员管理系统源码带短信平台数据库 SQL2008源码类型 WebForm
- 企业创新数据90-23年.dta
- AI一键扣图,一键去背景
- C++线程池、C++11标准库线程制作的线程池
- 同城定位付费进群完整源码+对接支付/详细教程/可用无问题
- C#CS框架小区物业管理系统源码数据库 Access源码类型 WinForm
- Alibaba-Dragonwell-Extended-21.0.5.0.5.9-x64-windows.zip