首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言計算第 N 個閏年:日期運算與閏年判斷完整實作

     編輯:關於C語言

給定起始年份與閏年序數 N,計算第 N 個閏年年份。本文實作標準格里高利曆閏年規則,解析日期運算邊界條件,提供高效遞增搜尋與數學公式雙重解法。

閏年判斷規則

// 標準格里高利曆閏年規則
int is_leap(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
  • 4 的倍數通常是閏年
  • 100 的倍數不是閏年 (例外)
  • 400 的倍數仍是閏年 (例外的例外)

遞增搜尋法完整實作

#include <stdio.h>

int is_leap(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

int main() {
    int test_cases;
    scanf("%d", &test_cases);
    
    while (test_cases--) {
        int start_year, n;
        scanf("%d %d", &start_year, &n);
        
        int count = 0;
        int year = start_year;
        
        // 從起始年份開始尋找第 n 個閏年
        while (count < n) {
            if (is_leap(year)) count++;
            if (count < n) year++;  // 找到第 n 個時不再遞增
        }
        
        printf("%d\n", year);
    }
    return 0;
}

邊界條件詳細分析

起始年份本身是閏年

輸入 2000 1 → 輸出 2000 (2000 是閏年,第 1 個即為自身)

跨世紀邊界

  • 1896 5 → 1896, 1904, 1908, 1912, 1916 (1900 非閏年被跳過)
  • 1996 5 → 1996, 2000, 2004, 2008, 2012 (2000 是閏年)

大數值測試

1 1000000 遞增法需百萬次迴圈,仍在毫秒級,但可用數學公式優化至 O(1)。

數學公式 O(1) 解法

利用 400 年週期包含 97 個閏年特性:


// 計算 1 年至 year 年底的閏年總數 (含 year)
long leap_count_to(long year) {
    return year/4 - year/100 + year/400;
}

// 二分搜尋第 n 個閏年
long nth_leap(long start, long n) {
    long target = leap_count_to(start - 1) + n;
    long low = start, high = start + n * 5;  // 上界估計
    
    while (low < high) {
        long mid = (low + high) / 2;
        if (leap_count_to(mid) >= target) high = mid;
        else low = mid + 1;
    }
    return low;
}

完整測試案例

起始年N結果說明
200012000起始即閏年
200112004下一個閏年
189651916跨越 1900 非閏年
199652012跨越 2000 閏年
20001020362000,04,08,12,16,20,24,28,32,36
1900119041900 非閏年
240012400400 倍數閏年
閏年計算程式執行示意 多測資輸出結果

常見錯誤與除錯

  1. 判斷邏輯錯誤:year%4==0 || year%400==0 錯誤包含 1900、2100
  2. 計數器位置:遞增在判斷之後,導致少算或多算
  3. 年份上限:int 最大 2147483647,年份運算安全
  4. 負年份:歷史年份需天文年份編號 (公元前 1 年 = 年份 0)

進階擴充功能

輸出閏年清單

void print_leaps(int start, int n) {
    int count = 0, year = start;
    while (count < n) {
        if (is_leap(year)) {
            printf("%d%c", year, (count == n-1) ? '\n' : ' ');
            count++;
        }
        year++;
    }
}

計算兩日期間閏年數


int leaps_between(int y1, int y2) {
    if (y1 > y2) { int t=y1; y1=y2; y2=t; }
    return leap_count_to(y2) - leap_count_to(y1-1);
}

效能比較

方法時間複雜度適用範圍實測 (N=10⁶)
遞增搜尋O(N)N < 10⁷~15ms
二分搜尋+公式O(log N)任意大 N<0.01ms
直接公式O(1)需推導閉形式理論最快

閏年計算看似簡單,實則包含曆法規則、邊界處理、演算法優化等核心程式設計技巧。從直觀遞增法理解問題本質,再進階至數學公式與二分搜尋,完整展現從正確性到效能的工程思維演進。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved