给定日期(年月日)求星期几(蔡勒公式?没那么简单!)

article/2025/11/11 12:53:51

前言

前几日做到一个机试题,给出一个日期,让你输出那天是星期几,这种题无疑两种思路:一是从今天(前提是知道今天日期及周几)开始推算,计算今天与目标日期差的天数再取模运算,考虑到还要考虑闰年什么的,立即推->用下一种方法;直接利用一个什么公式来计算(问题是这样算起来容易,但公式不好记啊啊啊)。

蔡勒公式

w = ( C / 4 − 2 C + Y + Y / 4 + 13 ( M + 1 ) / 5 + D − 1 ) % 7 w =(C/4-2C+Y+Y/4+13(M+1)/5+D-1)\%7 w=(C/42C+Y+Y/4+13(M+1)/5+D1)%7

其中 / / / 为除法运算,结果取整(即商), % \% % 为取模运算; C C C 表示已过世纪数,即本世纪减一, Y Y Y 表示 世纪内的年份,即一般是年份的后两位数字 M M M 代表月份,如果 M < 2 M<2 M<2,则加12,并且年份减1(即将某年的1月、2月,看作上一年的13月、14月来带入计算,并且这一步要先于计算 C C C D D D 表示日。

w w w 为 0 时表示星期日,不为0时, w w w是几便是星期几。

话不多说,上代码(C++),代码输入输出格式是按照机试格式要求来的

input:
2
2020 4 8
2000 2 5
output:
3
6
#include <iostream>
#include <cmath>using namespace std;
int cen(int y);int main(void)
{int n;int y, m, d;while (cin >> n){for (int i = 0; i < n; i++){cin >> y >> m >> d;if (m < 3){y--;m += 12;}	int y1 = y - cen(y)*100;int w = (y1 + y1/4 + cen(y)/4 - 2*cen(y) + 13*(m+1)/5 + d - 1) % 7;if (0 == w)w = 7;cout << w << endl;}}return 0;
}int cen(int y)	// 已过世纪数
{return y/100;
}

这样好像测试的两个例子都正确,但是真的有这么简单?╮(╯_╰)╭
输入如下测例试试

2006 4 4
2100 12 2

结果

-5
-3

所以问题出在哪呢,enmmm,结果是通过蔡勒公式直接计算出来的,结果为负就说明蔡勒公式的被除数部分 ( C / 4 − 2 C + Y + Y / 4 + 13 ( M + 1 ) / 5 + D − 1 ) (C/4-2C+Y+Y/4+13(M+1)/5+D-1) (C/42C+Y+Y/4+13(M+1)/5+D1) 可能为负,然后就涉及到负数取模的问题,,关于负数取模,百度一下就会发现不同的语言实现方法并不相同!

  • C/C++/Java 采用了 truncate 除法。
    -7 % 3 = -7 - (-7) / 3 * 3= -7 - (-2) * 3 = -7 + 6 = -1
  • python 则采用floor 除法
    -7 % 3 = -7 - (-7) / 3 * 3= -7 - (-3) * 3 = -7 + 9 = 2

可以看出两种取模方法根本在于除法是采用向上取整还是向下取整。很明显蔡勒公式中的负数取模方式采用的是向下取整!
这与 C++ 的负数取模方式不同,所以对于负数取模,我们需要进一步处理;

代码更改如下:

#include <iostream>
#include <cmath>using namespace std;
int cen(int y);	// 已过世纪数int main(void)
{int n;int y, m, d;while (cin >> n){for (int i = 0; i < n; i++){cin >> y >> m >> d;if (m < 3){y--;m += 12;}	int y1 = y - cen(y)*100;// or y1 = y % 100int w = (y1 + y1/4 + cen(y)/4 - 2*cen(y) + 13*(m+1)/5 + d - 1);if (w < 0)	// 负数取模w = 7 - (-w) % 7;elsew = w % 7;if (0 == w)w = 7;cout << w << endl;}}return 0;
}int cen(int y)	// 已过世纪数
{return y/100;
}

拓展

万年历(公历)

/* 输入日期(年月日),打印本月日历 **/
#include <iostream>
#include <iomanip>using namespace std;
int week(const int y, const int m, const int d);	// 计算一号是周几
void printMon(const int y, const int m, const int d);	// 打印月历
bool isLeap(const int y);	// 判断闰年int main(void)
{int y, m, d;cin >> y >> m >> d;printMon(y, m, d);return 0;
}int week(const int y, const int m, const int d)	// 利用蔡勒公式求星期几
{int y1 = y;int m1 = m;int d1 = d;if (m1 < 3){m1 += 12;y1--;}int cen = y1 / 100;int y2 = y1 % 100;int w = (y2 + y2/4 + cen/4 - 2*cen + 13*(m1+1)/5 + d1 - 1);if (w < 0)	// 负数取模w = 7 - (-w) % 7;elsew = w % 7;if (0 == w)w = 7;return w;
}void printMon(const int y, const int m, const int d)	// 打印月历
{int mon[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int day = mon[m-1];int w = week(y, m, d);if (isLeap(y) && 2==m)day++;cout << "Sun  " << "Mon  " << "Tues  " << "Wed  " << "Thur " << "Fri  " << "Sat\n";if (7 == week(y, m, 1)){for (int i = 1; i <= day; i++){cout << setiosflags(ios::right) << setw(3) << i << "  ";if (i % 7 == 0) // 周六后换行cout << endl;}}else{for (int i = 0; i < week(y, m, 1); i++)	// 控制一号前的距离cout << "     ";for (int i = 1; i <= day; i++){cout << setiosflags(ios::right) << setw(3)  << i << "  ";if ((i+week(y, m, 1)) % 7 == 0)	// 周六后换行cout << endl;}}cout << endl;
}bool isLeap(const int y)
{if (y%400==0 || (y%100!=0 && y%4==0))return true;elsereturn false;
}

效果:
在这里插入图片描述


http://chatgpt.dhexx.cn/article/iQSebehS.shtml

相关文章

欧拉计划题-19 (蔡勒公式)

欧拉计划题19 前言一 题目描述二 题解分析1.暴力求解&#xff08;低配版解法&#xff09;2.蔡勒公式&#xff08;公式法&#xff09; 三 题解代码 前言 欧拉计划是学习数学、数论选手遨游的海洋&#xff0c;700道题让你我越来越强。 打卡网址链接: link. 一 题目描述 题目链接…

C语言——蔡勒(Zeller)公式:快速将任意日期转换为星期数

蔡勒公式 情景引入公式介绍公式细节代码实现 情景引入 在日常生活中&#xff0c;我们有时候会遇到这样的问题&#xff1a;看到一个日期想知道这一天是星期几。对于这个问题&#xff0c;如果用编程的方式&#xff0c;应该怎么实现呢&#xff1f;你可能已经有思路了&#xff0c;比…

自用笔记58——蔡勒(Zeller)公式

请你编写一个程序来计算两个日期之间隔了多少天。 日期以字符串形式给出&#xff0c;格式为 YYYY-MM-DD&#xff0c;如示例所示。 示例 1&#xff1a; 输入&#xff1a;date1 “2019-06-29”, date2 “2019-06-30” 输出&#xff1a;1 示例 2&#xff1a; 输入&#xff1…

蔡勒公式与Python

蔡勒公式 &#xff08; Zeller formula&#xff09; 作用&#xff1a;从年月日推算星期几 来源&#xff1a;罗马教皇格里高利十三世在1582年组织了一批天文学家&#xff0c;根据哥白尼日心说计算出来的数据&#xff0c;对儒略历作了修改。将1582年10月5日到14日之间的10天宣布…

蔡勒(Zeller)公式理解Get(√)

Preface 偶然做到日期相关题目&#xff0c;了解到Zeller公式。不甘心停留在使用阶段&#xff0c;便想掌握其推导过程。 只适用于格利戈里历法&#xff0c;也就是现今的公历。 1. Zeller公式 标准形式 计算1582年10月4日或之前日期 (罗马教皇决定在1582年10月4日后使用格利戈里…

C语言——蔡勒(Zeller)公式的使用

C语言——蔡勒公式的使用 蔡勒公式简介&#xff1a; 蔡勒&#xff08;Zeller&#xff09;公式&#xff0c;是一个计算星期的公式&#xff0c;随便给一个日期&#xff0c;就能用这个公式推算出是星期几。 计算公式&#xff1a; 核心公式&#xff1a; w(y[y/4][c/4]-2c[26(m1…

c++ operator百样操作符重载(详解)

目录 一、operator &#xff1a;等号判断重载 二、operator &#xff1a; 等号赋值重载 三、operator ! : 不等于重载 四、operator> &#xff1a; 大于号 或者 小于号 重载 五、operator << &#xff1a;输入重定向重载 六、operator &#xff1a;加号重载 …

操作符重载!看这篇就够了!

实现一个操作符重载的方式通常有两种情况&#xff1a; 将操作符重载实现为类的成员函数。操作符重载实现为非类的成员函数(即全局函数)。 将操作符重载实现为类的成员函数 在类体中声明(定义)需要重载的操作符&#xff0c;声明方式跟普通的成员函数一样&#xff0c;只不过操作符…

C++基本操作符重载

基本操作符重载 基本操作符重载reference 基本操作符重载 操作符重载指的是将 C 提供的操作符进行重新定义&#xff0c;使之满足我们所需要的一些功能。 在 C 中可以重载的操作符有&#xff1a; - * / % ^ & | ~ ! < > - * / % ^ & | <…

【Groovy】map 集合 ( map 集合操作符重载 | + 操作符重载 | 代码示例 )

文章目录 一、map 集合 " " 操作符重载二、代码示例 一、map 集合 " " 操作符重载 对 map 集合使用 " " 操作符 , 操作符两侧都是 map 集合 , 调用的是 map 集合的 plus 方法 , plus 函数有 2 2 2 个参数 : 第一个参数 , Map<K, V> l…

【Groovy】map 集合 ( map 集合操作符重载 | - 操作符重载 | 代码示例 )

文章目录 一、map 集合 " - " 操作符重载二、完整代码示例 一、map 集合 " - " 操作符重载 对 map 集合 使用 " - " 操作符 , 相当于调用了 map 集合的 minus 方法 , 该方法传入 2 2 2 个参数 : Map<K,V> self 参数 : 相当于 " - &…

【C++】操作符重载

注意&#xff1a;操作符重载可以当做“自定义类的运算” 1 为什么需要操作符重载&#xff1f; 对于基础的变量&#xff0c;int等&#xff0c;不需要重载就知道如何做&#xff0c;但是对于自定义类&#xff0c;就无法进行运算&#xff0c;比如复数类。 2 操作符重载总结 1&…

C++ 操作符重载

输出操作符"<<" 和输入操作运算符">>" 操作符重载&#xff0c;也叫运算符重载&#xff0c;是C的重要组成部分&#xff0c;它可以让程序更加的简单易懂&#xff0c;简单的运算符使用可以使复杂函数的理解更直观。 操作符重载可对 已有的运算…

C++-操作符重载

定义&#xff1a; Salesitem.h /* * This file contains code from "C Primer, Fifth Edition", by Stanley B. * Lippman, Josee Lajoie, and Barbara E. Moo, and is covered under the * copyright and warranty notices given in that book: * * "Copyrig…

c++操作符重载

转自https://www.cnblogs.com/xudong-bupt/p/3557525.html 1.什么是操作符重载 可以使用分词将操作符重载理解为&#xff1a;操作符重载。 C中的操作符很多&#xff0c;如&#xff0c;-&#xff0c;*&#xff0c;\等等。 C中的重载也是C中面向对象多态的体现。 简单说操作符重…

操作符重载——C/C++学习笔记

此篇文章来自于网上&#xff0c;作为自己学习中的笔记&#xff0c;若有侵权行为&#xff0c;请告之&#xff0c;24小时之内必删除&#xff01;下面就转入正题吧&#xff01; 一、什么是操作符重载&#xff1f; 一看到重载&#xff0c;很容易就让人联想到成员函数重载&#xff0…

什么是操作符重载

一、什么是操作符重载 操作符重载可以分为两部分&#xff1a;“操作符”和“重载”。说到重载想必都不陌生了吧&#xff0c;这是一种编译时多态&#xff0c;重载实际上可以分为函数重载和操作符重载。运算符重载和函数重载的不同之处在于操作符重载重载的一定是操作符。我们不妨…

前端知识点总结 Vue JS CSS

前端知识点 MVVM和MVC的区别什么是Vue生命周期钩子函数触发顺序 VueVue优点父子通信&#xff0c;兄弟通信指令V-if和V-show区别 Vue-loaderVue-key的作用v-modalVue data必须是函数的问题Vue slot Vue-router多个router-viewroute与router的区别导航守卫懒加载 ES6JavaScript同…

JavaScript进阶之手写Promise

前言 Promise异步编程的一种解决方案&#xff0c;比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现&#xff0c;ES6 将其写进了语言标准&#xff0c;统一了用法&#xff0c;原生提供了Promise对象。这里手写一次&#xff0c;希望能和大家一起彻底…

【数据库】MongoDB数据库详解

目录 一&#xff0c;数据库管理系统 1&#xff0c; 什么是数据库 2&#xff0c;什么是数据库管理系统 二&#xff0c; NoSQL 是什么 1&#xff0c;NoSQL 简介 2&#xff0c;NoSQL数据库 3&#xff0c;NoSQL 与 RDBMS 对比 三&#xff0c;MongoDB简介 1&#xff0c; MongoDB 是什…