当前位置: 首页 > news >正文

闰年的历史由来与C语言实现详解

原文:https://kashima19960.github.io/2025/07/16/C语言/闰年的历史由来与C语言实现详解/

前言

最近在研究RTC时钟,所以难以避免需要计算日历的时间,但不是每一年都是365天,所以必须考虑闰年的情况,这篇文章我除了会讲述程序,还会详细阐述闰年的历史故事及其由来,因为我认为学习任何一个东西,在知道“怎么用”以后,下一步就是知道“底层原理是什么” 如果你是着急知道程序怎么写,那可以先跳过闰年的历史以及计算规则的原理,等以后再去了解

程序实现

满足两大规则即可

  1. 能被 4 整除,但不能被 100 整除。

    • 例如:2024 年能被 4 整除,但不能被 100 整除,所以是闰年。
    • 例如:1900 年能被 4 整除,也能被 100 整除,不满足这个条件。
  2. 能被 400 整除。

    • 例如:2000 年能被 400 整除,所以是闰年(这个条件优先于“能被100整除”的规则)。

总结成一句话就是:四年一闰,百年不闰,四百年再闰

#include <stdio.h> // 引入标准输入输出库,这样我们才能使用 printf 和 scanf 函数int main(void) {// 1. 声明一个整型变量,用于存储用户输入的年份int year;// 2. 提示用户输入年份printf("请输入一个年份 (例如: 2024): ");// 3. 读取用户从键盘输入的内容// scanf("%d", &year);// - "%d" 表示我们期望读取一个十进制整数。// - &year 表示将读取到的整数存放到变量 year 的内存地址中。//   注意:scanf 的变量参数前一定要加 '&' 地址符(数组名除外)。if (scanf("%d", &year) != 1) {// 一个简单的输入验证,如果用户输入的不是数字,scanf会返回0或EOFprintf("输入无效,请输入一个有效的年份数字。\n");return 1; // 返回一个非零值,表示程序出错退出}// 判断是否为闰年的核心代码, 有两种写法,我这里比较推荐写法1,代码简洁很多,而且能跟两大规则契合,写法2没那么直观//写法1if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {printf("%d 年是闰年。\n", year);} else {printf("%d 年是平年。\n", year);}//写法2// if (year % 4 == 0)// {//     if (year % 100 == 0)//     {//         if (year % 400 == 0)//             printf("%d 年是闰年。\n", year);//         else//             printf("%d 年是平年。\n", year);//     }//     else//         printf("%d 年是闰年。\n", year);// }// else//     printf("%d 年是平年。\n", year);return 0;
}

闰年计算规则的底层原理

不感兴趣或者时间有限的话,这部分可以不看

前因:最根本的矛盾 —— 地球公转与日历的“对不齐”

我们故事的起点,是宇宙中一个非常基本但又有点“逼死强迫症”的事实:

地球围绕太阳公转一周的精确时间(天文学上称为“回归年”),并不是一个整数。

这个精确时间大约是 365.2422 天

而我们人类日常使用的日历,为了方便,一年是 365 天

你看,矛盾就出现了:
365.2422 - 365 = 0.2422

每年,我们的日历都会比地球的实际公转周期快了 0.2422 天(大约是5小时48分46秒)。这个误差看起来很小,但时间一长,后果会非常严重。

  • 1年后,日历比季节快了约 0.2422 天。
  • 4年后,日历比季节快了约 0.2422 * 4 ≈ 0.9688 天,差不多整整 1 天
  • 100年后,日历会比季节快了 24.22 天

这意味着,如果不做任何修正,几百年后,本该是炎炎夏日的七月,可能会变成春寒料峭的时节。日历上的日期和实际的季节(春分、夏至、秋分、冬至)会完全错位。

为了让日历年和回归年能够对齐,保证日历能准确反映季节变化,人类必须想办法“填”上这个误差。“闰年”就是为了这个目的而诞生的。


第一步:早期粗略的解决方案 —— 儒略历 (Julian Calendar)

时间: 公元前46年
人物: 罗马共和国的统治者,尤利乌斯·凯撒 (Julius Caesar)

凯撒和他的天文学家们(如索西琴尼)已经认识到了这个问题。他们进行了当时最精确的计算,得出的回归年长度是 365.25 天

365.25 这个数字非常好处理。0.25 不就是 1/4 吗?

于是,他们制定了第一条简单而优雅的规则:

“每四年设置一个闰年。”

在闰年这一年,增加一天(放在二月底),使得这一年有366天。我们来算一下这种方法下,平均每年的天数:
(365 + 365 + 365 + 366) / 4 = 1461 / 4 = 365.25 天。

完美!这套历法被称为“儒略历”,它在接下来的1600多年里,成为了欧洲的标准。


第二步:新矛盾的出现 —— 儒略历的微小误差累积成大问题

儒略历是一个巨大的进步,但它并非完美。还记得吗?

  • 儒略历的平均年长365.25
  • 地球的实际回归年365.2422

两者之间仍然存在一个微小的误差:
365.25 - 365.2422 = 0.0078

儒略历的每年,实际上比回归年长了 0.0078 天。这意味着,儒略历走得太慢了,每过一年,季节的实际节点(比如春分)就会在日历上提前一点点。

这个误差有多大呢?

  • 大约每 1 / 0.0078 ≈ 128 年,就会累积出 1天 的误差。
  • 到了16世纪(公元1500多年),儒略历已经实行了超过1600年。累积的误差大约是 0.0078 * 1600 ≈ 12.5 天。

这个误差在当时造成了一个非常具体且严重的问题,尤其对于基督教世界。复活节的日期是根据“春分月圆之后”来计算的。而当时日历上的春分(3月21日)和天文学上实际的春分,已经差了十几天!这让教会无法准确地确定这个最重要的宗教节日。


第三步:终极的精准修正 —— 格里高利历 (Gregorian Calendar) 的诞生

时间: 公元1582年
人物: 罗马教皇格里高利十三世 (Pope Gregory XIII)

为了解决这个迫在眉睫的问题,教皇格里高利十三世召集了顶尖的天文学家和数学家(如克拉维乌斯),进行了历法改革。这次改革有两个目标:

  1. 修正存量错误:把过去1600年累积的误差一次性抹掉。
  2. 改进规则,防止未来再犯:设计一套更精确的闰年规则。

修正存量错误的方法简单粗暴:教皇下令,在1582年10月4日之后,直接跳到10月15日。于是,历史凭空消失了10天,使得第二天的春分重新对准了3月21日。

改进规则的方法则充满了数学智慧,这就是我们今天所用规则的由来:

  1. 分析问题:问题的根源是儒略历的闰年太多了。它每400年里,会设置100个闰年。而累积的误差 0.0078 天/年,在400年里会造成 0.0078 * 400 ≈ 3.12 天的误差。

  2. 找到方案:这意味着,我们大约需要在每400年里,减少3个闰年

  3. 设计规则:怎么才能巧妙地、有规律地在400年里减少3个闰年呢?

    • 首先,保留儒略历的基本规则:“能被4整除的是闰年”。这保证了大部分情况是正确的。
    • 然后,想办法去掉3个闰年。一个很自然的想法是在世纪年份(1700, 1800, 1900, 2000…)上做文章。
    • 于是,补充规则诞生了:“能被100整除的年份,不再是闰年”。
      • 这样一来,在400年里(比如从1601到2000),1700、1800、1900、2000这四个年份本来是闰年,现在都变成了平年。我们成功地去掉了4个闰年。
    • 但我们的目标是去掉3个。现在多去掉了1个,怎么办?再加回来一个!
    • 最终的补充规则来了:“虽然能被100整除的不是闰年,但如果它还能被400整除,那么它依然是闰年”。
      • 这样,在1700, 1800, 1900, 2000这四年中,前三年(不能被400整除)被排除在闰年之外,但第四年(2000年,能被400整除)被重新“豁免”,恢复了闰年身份。
      • 完美!我们不多不少,正好在400年里去掉了3个闰年。

这就是我们今天使用的“格里高利历”(简称公历)的闰年判断法则。

我们再来算一下公历的平均年长:

  • 在400年里,共有 100 - 3 = 97 个闰年。
  • 总天数 = (365 * 400) + 97 = 146000 + 97 = 146097 天。
  • 平均年长 = 146097 / 400 = 365.2425 天。

这个数字 365.2425 与地球回归年的精确值 365.2422 已经非常非常接近了,误差小到每3000多年才会产生1天的偏差。对于人类文明来说,这已经足够精确了。

结论

所以,闰年的规则并不是凭空想出来的,而是人类为了弥合“人为规定的日历”与“客观的宇宙规律”之间的缝隙,历经上千年,通过不断观察、计算和修正,最终总结出的一套极其精妙的数学与天文规则。它清晰地展现了从一个粗略模型(儒略历)到一个精准模型(格里高利历)的科学演进过程。

http://www.dtcms.com/a/283012.html

相关文章:

  • 7.16 拓扑排序 | 欧拉回路 |链表排序 前缀和
  • Vue在线预览Excel和Docx格式文件
  • Redis学习其一
  • Python学习之路(十三)-常用函数的使用,及优化
  • Redis读写策略深度解析:高并发场景下的缓存兵法
  • python基础语法9,用os库实现系统操作并用sys库实现文件操作(简单易上手的python语法教学)
  • 猫眼娱乐IOS开发一面手撕算法
  • 嵌入式学习笔记--MCU阶段--DAY06DHT11练习
  • AR智能巡检:电力行业数字化转型的“加速器”
  • 基于Llama的RAG 3种模型配置方法
  • 51c自动驾驶~合集7
  • 基于C#开发solidworks图库中文件(SLDPRT,SLDASM,SLDDRW等)转换为HTML和PDF,提供批量和实时转换
  • AI产品经理面试宝典第28天:自动驾驶与智慧交通融合面试题与答法
  • 自动驾驶激光3D点云处理系统性阐述及Open3D库函数应用
  • MR 处于 WIP 状态的WIP是什么
  • 小模型的价值重估:从“缩水版DeepSeek”到AI系统的基础执行单元20250716
  • Linux 挂载新磁盘导致原文件被隐藏解决方案
  • 【代码】Matlab鸟瞰图函数
  • sqli-labs靶场通关笔记:第23关 注释符过滤
  • 叉车机器人如何实现托盘精准定位?这项核心技术的原理和应用是什么?
  • 静默的田野守护者:Deepoc具身智能如何让除草机器人读懂大地密语
  • Mybatis08-使用pageHelper
  • 本地 AI 问答机器人搭建项目(Ollama + Qwen-7B + LangChain + FastAPI)
  • AI对话聊天与桌宠工具调研报告
  • 【案例分享】基于FastCAE-Acoustics软件对车门进行噪声预测
  • 移动平板电脑安全管控方案
  • 祥云系统开源云商城程序全开源版 个人程序云商城(源码下载)
  • 前端学习7:CSS过渡与动画--补间动画 (Transition) vs 关键帧动画 (Animation)
  • xss-lab1-8关
  • AdsPower 功能详解 | 应用中心使用指南:插件统一管理更高效、更安全!