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

【看到哪里写到哪里】算闰年的(year 3) == 0

【??BUG??】在MYSQL源码里面有一段,算每年的天数。其中用到了两个很有意思的

1)(year & 3) == 0

2)(year % 400 == 0 && year),为什么要 &&year呢?

>>>>>mysql-server/mysys/my_time.cc 的128~137行/**Calc days in one year.@note Works with both two and four digit years.@return number of days in that year
*/
uint calc_days_in_year(uint year) {return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366: 365);
}

一般的算闰年的写法很简单

一、闰年的基本定义与规则

闰年是为了弥补因公历纪年中 “平年”(365 天)与地球实际公转周期(约 365.2422 天)的时间差而设立的。具体判断规则如下:

1. 普通闰年判断规则

满足以下条件之一的年份为闰年:

  • 能被 4 整除且不能被 100 整除
    例:2004 年(2004÷4=501,2004÷100=20.04)是闰年;
    1900 年(1900÷4=475,但 1900÷100=19)不是闰年。
2. 世纪闰年判断规则
  • 能被 400 整除的整百年份为闰年。
    例:2000 年(2000÷400=5)是闰年;
    1800 年(1800÷400=4.5)不是闰年。

二、规则拆解与逻辑说明

可用逻辑表达式表示为:
(年份 % 4 == 0 且 年份 % 100 != 0) 或 年份 % 400 == 0

  • 为什么除以 4?
    地球公转约 365.2422 天,每 4 年积累约 0.9688 天,接近 1 天,故每 4 年设 1 个闰年(加 1 天)。

  • 为什么除以 100 的例外?
    每 4 年加 1 天会导致误差:400 年累计多算约 3 天。因此规定 “能被 100 整除但不能被 400 整除的年份” 不算闰年(如 1900 年、2100 年),以修正误差。

  • 为什么除以 400 的例外?
    进一步修正误差:每 400 年中,原本应排除 3 个整百年(如 1700、1800、1900),但保留能被 400 整除的年份(如 2000 年),使 400 年内闰年数量为 97 个,更接近实际公转周期。

C语言写个简单的函数,首先要判断不能<=0,再做判断。

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

=====================================================================

但是前面那段mysql的程序是什么意思呢?

在闰年判断函数中,(year & 3) == 0 是一种高效的位运算技巧,用于替代 year % 4 == 0 判断一个年份是否能被 4 整除。

一、位运算原理:为什么 (year & 3) == 0 等价于 year % 4 == 0

1. 4 的倍数的二进制特征

一个整数能被 4 整除,当且仅当其二进制表示的最后两位是 0

例如:

  • 4 的二进制:100(最后两位是 00)
  • 8 的二进制:1000(最后两位是 00)
  • 12 的二进制:1100(最后两位是 00)
  • 15 的二进制:1111(最后两位是 11,不能被 4 整除)
2. 位与运算(&)的作用

3 的二进制是 0011(假设是 32 位整数,则为 000...0011)。当一个数 year 与 3 进行位与运算时:

year & 3 等价于:只保留 year 的二进制表示的最后两位,其余位清零

因此:

  • 若 year 能被 4 整除(最后两位是 00),则 year & 3 的结果为 00(十进制 0)。
  • 若 year 不能被 4 整除(最后两位不为 00),则 year & 3 的结果为 0110 或 11(十进制 1、2 或 3)。

二、为什么用位运算替代取模(%)?

1. 性能优势
  • 取模运算(%):在 CPU 中通常需要除法指令,涉及多次减法或移位操作,计算开销较大。
  • 位与运算(&):直接对二进制位进行操作,仅需一次逻辑运算,速度远快于取模。
2. 编译器优化的局限性

虽然现代编译器可能会将 year % 4 优化为 year & 3(当除数是 2 的幂时),但:

  • 不同编译器的优化能力不同,手动使用位运算能确保在所有环境下都高效。
  • 代码可读性不受影响,因为 (year & 3) == 0 的含义很直观(“判断是否为 4 的倍数”)。

三、原代码的闰年判断逻辑拆解

原代码为:

return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366 : 365);
1. 逻辑表达式的结构

整体逻辑等价于:

if ((year & 3) == 0 && (year % 100 != 0 || year % 400 == 0)) {return 366;  // 闰年
} else {return 365;  // 平年
}
2. 核心判断步骤
  • 第一步:判断是否为 4 的倍数(year & 3) == 0 替代 year % 4 == 0,高效检查年份是否能被 4 整除。
  • 第二步:判断是否为 100 的倍数year % 100 != 0(原代码中 year % 100 为真等价于 year % 100 != 0)。
  • 第三步:判断是否为 400 的倍数year % 400 == 0
3. 特殊情况处理:&& year 的作用

原代码中 (year % 400 == 0 && year) 中的 && year 是冗余的,因为:

  • 年份 year 是 uint(无符号整数),其值 ≥ 0。
  • 当 year = 0 时,year % 400 == 0 为真,但 && year 为假,结果为平年(符合实际,因为公元 0 年不存在)。
  • 当 year > 0 时,&& year 恒为真,不影响判断。

相关文章:

  • 泉州模板建站源码线上宣传有哪些好的方式方法
  • 什么叫宣传型网站站点推广是什么意思
  • 自己做网站如何放置在服务器中关键词林俊杰mp3下载
  • 如何浏览香港网站优化网站怎么做
  • 商城网站源码下载常用的网络营销方法及效果
  • 网站后台登陆不了网站建设的基本
  • Selenium 二次封装通用页面基类 BasePage —— Python 实践
  • Windows下安装zookeeper
  • ros (二) 使用消息传递点云+rviz显示
  • web目录扫描-御剑
  • Redis跳表(skiplist)底层原理浅析
  • 使用亮数据网页抓取API自动获取Tiktok数据
  • matlab机器人工具箱(Robotics Toolbox)安装及使用
  • 【EDA软件】【应用功能子模块网表提供和加载编译方法】
  • 重置 MySQL root 密码
  • 前端面试专栏-主流框架:13.vue3组件通信与生命周期
  • webman 利用tcp 做服务端 对接物联网
  • C# LINQ语法
  • Boss:攻击
  • 【MQTT】常见问题
  • MySQL之视图深度解析
  • 第2章,[标签 Win32] :编写兼容多字节字符集和 Unicode 字符集的 Windows 程序
  • 【DevTools浏览器开发者工具反调试之无限Debugger跳过】
  • SpringBoot高校党务系统
  • PyTorch RNN实战:快速上手教程
  • Python 数据分析与可视化 Day 7 - 可视化整合报告实战