基姆拉爾森公式 (Kim Larsen Formula) 可直接由年月日算出星期幾 (0=週一...6=週日),無需迭代累加,效率極高。本文實作互動式萬年曆程式:輸入年份與月份,自動判斷閏年與月天數,套用公式得知 1 號星期幾,再按週對齊列印完整月曆。程式碼採 C++ 風格輸入輸出,邏輯純 C,易於移植。
// 輸入:y 年, m 月(1-12), d 日
// 輸出:0=週一, 1=週二, ..., 6=週日
if (m == 1 || m == 2) { m += 12; y--; } // 視為上一年 13/14 月
int w = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7;
if (w == 0) w = 7; // 調整為 1=週一 ... 7=週日
bool is_leap(int y) {
return (y%4==0 && y%100!=0) || (y%400==0);
}
int month_days(int y, int m) {
static const int md[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if (m == 2) return md[2] + is_leap(y);
return md[m];
}
mdays 與 1 號星期 w (1-7)。w-1 個空白欄位對齊第一週。mdays,每印 7 個換行;最後補齊換行。#include <stdio.h>
#include <stdbool.h>
bool is_leap(int y) { return (y%4==0 && y%100!=0) || (y%400==0); }
int month_days(int y, int m) {
static const int md[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
return (m==2) ? md[2]+is_leap(y) : md[m];
}
int weekday_kim(int y, int m, int d) {
if (m <= 2) { m += 12; y--; }
int w = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7;
return w == 0 ? 7 : w; // 1=Mon ... 7=Sun
}
void print_calendar(int y, int m) {
int mdays = month_days(y, m);
int w = weekday_kim(y, m, 1);
printf("\n %d 年 %2d 月\n", y, m);
printf(" 一 二 三 四 五 六 日\n");
for (int i = 1; i < w; i++) printf(" ");
for (int d = 1; d <= mdays; d++) {
printf("%3d ", d);
if ((d + w - 1) % 7 == 0) printf("\n");
}
printf("\n");
}
int main() {
int y, m;
while (printf("\n請輸入年份 月份 (如 2024 5),0 0 結束:"),
scanf("%d %d", &y, &m) == 2 && (y||m)) {
print_calendar(y, m);
}
return 0;
}
請輸入年份 月份 (如 2024 5),0 0 結束:2024 2
2024 年 2 月
一 二 三 四 五 六 日
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29
基姆拉爾森公式以 O(1) 時間解決星期計算,配合簡單的格式化邏輯,即可構建高效、無依賴的萬年曆核心,是嵌入式裝置、CLI 工具、教學示範的首選演算法。