黑色星期五问题(利用蔡勒公式和不利用蔡勒公式两种算法)

在西方,星期五和数字 13 都代表着坏运气,两个不幸的个体最后结合成超级不幸的一天。所以,不管哪个月的十三日又恰逢星期五就叫“黑色星期五”。

要求:输入年份,输出是:判断该年是否包含黑色星期五,如包含,给出具体日期


蔡勒(zeller)公式:随便给一个日期,就能用这个公式推算出是星期几 

W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1

(或者是:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

若要计算的日期是在1582104日或之前,公式则为

w=y+[y/4]+[c/4]-2c+[13(m+1)/5]+d+2

w:星期; w7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六

c:世纪(前两位数)

y:年(后两位数)

m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的12月要看作上一年的1314月来计算,比如200311日要看作2002年的131日来计算)

  d:日

利用泰勒公式求某一天是星期几:

#include<iostream>
#include<string>
using namespace std;
int main(){
int y,m,d,w;
while(cin>>y>>m>>d){
  int c=y/100;
  y=y-100*c;
      if(m<3){
         m+=12;
         y-=1;
      }
  w=c/4-2*c+y+y/4+13*(m+1)/5+d-1;
  while(w<0) w+=7;
  	w%=7;
  	}
string week[7]= {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
    cout<<week[w]<<endl;
    
}

利用蔡勒公式求特定年份有没有黑色星期五:

#include <iostream>
using namespace std;
int main()
{    int friday(int,int,int);
     int y,m,d=13,w;
     cout<<"input a year:"<<endl;
     cin>>y;
     int cont=0;
     for(m=1;m<13;++m){
     	if(friday(y,m,d))
     	  cout<<"dark friday:"<<m<<"\t"<<d<<"\t"<<endl;
   cont++;      	       	  
     }
  return 0;  
}
int friday(int y,int m,int d){    //利用蔡勒公式 
  	int c=y/100;
    y=y-100*c;
    int w;
    if(m<3){      //1,2月被看作上一年的13,14月 
    	m+=12;
    	y-=1;
    } 
    w=c/4-2*c+y+y/4+13*(m+1)/5+d-1;
    while(w<0) w+=7;
  	w%=7;
  	if(w==5)
  	return 1;
  	else return 0;
}


还可以检测是不是每一年都有黑色星期五:

#include<iostream>
using namespace std;
int friday(int,int,int);
int main(){
int y,m,d=13;
for(y=0000;y<2013;++y){
  int cont=0;
  int year=y; 
  for(m=1;m<13;++m){
  	 if(friday(y,m,d))
           cont++; 
  	}
  	if(cont==0)
cout<<year<<"年没有黑色星期五"<<endl;
}
}
int friday(int y,int m,int d){    //利用蔡勒公式 
  	int c=y/100;
    y=y-100*c;
    int w;
    if(m<3){      //1,2月被看作上一年的13,14月 
    	m+=12;
    	y-=1;
    } 
    w=c/4-2*c+y+y/4+13*(m+1)/5+d-1;
    while(w<0) w+=7;
  	w%=7;
  	if(w==5)
  	return 1;
  	else return 0;
}
经检测,从公元0 年开始,确实是 每一年都有黑色星期五


如果不用蔡勒公式,那就比较复杂了,首先看当年有没有闰年。

求闰年的简单程序,计算显示出0~2012年的闰年:

#include <iostream>
using namespace std;
int leapyear(int);
int main()
{
        int cont=0;
for(int year=0;year<2013;++year){
    	  if(leapyear(year)){
    	  cout<<year<<"\t";
    	  cont++;
    	  if(cont%5==0)
    	  cout<<endl;
    }    	  
    }
    return 0;
}
int leapyear(int year){
if((year%400==0) || (year%100!=0) && (year%4==0))
      return 1;
    else
  return 0;  
}



要计算那一天是星期几,还可以用这样的式子:

闰年时((year-1)*365+(year-1)/4-year/100+year/400+b[i]+1)%7==5

平年时((year-1)*365+year/4-year/100+year/400+a[i]+1)%7==5

其中a[i]和b[i]指的是该年1号到现在的天数(正如下面程序所示),这是因为我们知道公元1年1月1日是星期一。


利用这个leapyear的子程序,求黑色星期五:

#include<iostream>
using namespace std;
int leapyear(int);
typedef struct 
{
   int month;
   int day;
}Data;  
int main()
{
  Data data[12];    //存放特定年份的黑色星期五的日期,个数不可能超过12个 
  int a[13]={0,12,43,71,102,132,163,193,224,255,285,316,346};
  int b[13]={0,12,43,72,103,133,164,194,225,256,286,317,347};//闰年时
  int n=0,i,year;
  cin>>year;
  if(leapyear(year))//闰年时
  {
    for(i=1;i<=12;i++)
    {
      if(((year-1)*365+(year-1)/4-year/100+year/400+b[i]+1)%7==5)
      {
        data[n].month=i;
        data[n].day=13;
        n++;
      }
    }
  }
  else//平年
  {
    for(i=1;i<=12;i++)
    {
      if(((year-1)*365+year/4-year/100+year/400+a[i]+1)%7==5)   //计算公元到现在一共多少天 
      //公元1年1月1日是星期一 
      {
        data[n].month=i;
        data[n].day=13;
        n++;
      }
    }
  }   
  if(n==1)
  {
   cout<<"There is "<<n<<" Black Friday in year "<<year<<endl<<"It is ";
    cout<<year<<"."<<data[0].month<<"."<<data[0].day<<endl; 
  }
  else
  {
    cout<<"There is "<<n<<" Black Friday in year "<<year<<endl<<"They are "<<endl;;
    for(i=0;i<n;i++) cout<<year<<"."<<data[i].month<<"."<<data[i].day<<endl; ;
  }
  return 0;
}
int leapyear(int year){
if((year%400==0) || (year%100!=0) && (year%4==0))
      return 1;
    else
  return 0;  
}


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值