21ic电子技术开发论坛 单片机与嵌入式系统 侃单片机论坛 推导还是应该**3月为基月的原则
发新帖我要提问
12下一页
返回列表
打印

推导还是应该**3月为基月的原则

[复制链接]
5463|36
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wsl_5631|  楼主 | 2008-8-13 17:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我在网上下载了一篇您的2004年的** 新编万年历算法。有点问题像您请教。


unsigned char WeekDay(unsigned char c, unsigned char y, unsigned char m, 
unsigned char d)
{
unsigned char week, day;
  c &= 0x03;//百年%4
  c = c | (c << 2);//百年%4*5
  day = WeekTab[m - 1];//月表
  week = day >> 5;//月星期数
  day &= 0x1f;//月天数
  if ((m < 3) && !((c == 0) | (y & ((y & 0x03) == 0)))){//平年
    if (m == 2) day--;//平年月天数
    week++;//平年月表+1
  }
  y = y + (y >> 2);//年+年/4
  week = (week + c + y + d + 2) % 7;//(星期=百年%4*5+年+年/4+月表+日+2)%7
  return (week << 5) | day;//返回星期和月天数
}


  if ((m < 3) && !((c == 0) | (y & ((y & 0x03) == 0)))) 这句 计算平年的公式搞不懂。
0401应该是平年, C == 4 y==1 代入去计算。
c &= 0x03;//百年%4
 c = c | (c << 2);//百年%4*5
运算后C==0;

!((c == 0) | (y & ((y & 0x03) == 0)) 
应该等于0 不是平年

欢迎指正。






相关帖子

来自 2楼
hotpower| | 2008-9-6 09:34 | 只看该作者

这个算法实际是把月星期表进行了代换

月星期表+日+2天 等效为公式 (13 * m + 8)/ 5

再“转帖”我当时的“四百年历”的帖子:
推导过程:
1。平年365天(52周+1天),闰年366天(52周+2天)。平年2月28天,闰年2月29天。
   由于公元1月1日设为星期六,故3月1日为星期三。         ——注意这个“三”
   为使算法达到最简,故本算法以“星期”为计算单位。且选3月1日为基月。
2。每400年整一闰,或每4年且不为百年的一闰。
   百年%4=0闰或(年%4=0并且年<>0)闰。
3。每 4年(3个平年+1个闰年)共208周+5天                  ——注意这个“5天”
   每百年共100*(208周+5天)-1天=5217周+5天              ——注意这个“5天”(整
百年暂设为平年)
   每400年共4*(5217周+5天)+1天(整400年闰)=20871周+0天——注意这个“0天”和
“1天”(4个整百年只有一个闰年)
   即400年一轮回!(原来万年历400年前是一家)
4。万年3月1日星期算法(记住那个三)
   公式:某年3月1日星期几=(3天+百年%4*5天+年/4*5天+年%4+月星期表+日-1天)%7
         某年3月1日星期几=(百年%4*5天+年/4*5天+年%4+月星期表+日+2天)%7
   或    某年3月1日星期几=(百年%4*5天+年+年/4+月星期表+日+2天)%7
   
   闰4百年3月1日星期算法(百年%4=0)
   公式:某年3月1日星期几=(年+年/4+月星期表+日+2天)%7
   例:0000年3月1日星期几=(0+0/4+0+1+2)%7=3%7=星期三
       1600年3月1日星期几=(0+0/4+0+1+2)%7=3%7=星期三
       2000年3月1日星期几=(0+0/4+0+1+2)%7=3%7=星期三
       2001年3月1日星期几=(1+1/4+0+1+2)%7=4%7=星期四
       2004年3月1日星期几=(4+4/4+0+1+2)%7=8%7=星期一
       2008年3月1日星期几=(8+8/4+0+1+2)%7=13%7=星期六
       2042年3月1日星期几=(42+42/4+0+1+2)%7=55%7=星期六

   平4百年3月1日星期算法(百年%4<>0)
   公式:某年3月1日星期几=(百年%4*5天+年+年/4+月星期表+日+2天)%7
   例:1700年3月1日星期几=(17%4*5+0+0/4+0+1+2)%7=8%7=星期一(注意:1700年是平
年)
       1800年3月1日星期几=(18%4*5+0+0/4+0+1+2)%7=13%7=星期六(注意:1800年是平
年)
       1900年3月1日星期几=(19%4*5+0+0/4+0+1+2)%7=18%7=星期四(注意:1900年是平
年)
       1901年3月1日星期几=(19%4*5+1+1/3+0+1+2)%7=19%7=星期五
       1918年3月1日星期几=(19%4*5+18+18/4+0+1+2)%7=(15+22+3)%7=40%7=星期五
       1958年3月1日星期几=(19%4*5+58/4*5+58%4+3)%7=(15+70+2+3)%7=90%7=星期六
       1988年3月1日星期几=(19%4*5+88/4*5+88%4+3)%7=(15+110+0+3)%7=128%7=星期二
       1999年3月1日星期几=(19%4*5+99/4*5+99%4+3)%7=(15+120+3+3)%7=141%7=星期一
       2100年3月1日星期几=(21%4*5+0/4*5+0%4+3)%7=(5+0+0+3)%7=8%7=星期一(注意:
2100年是平年)
       2101年3月1日星期几=(21%4*5+1/4*5+1%4+3)%7=(5+0+1+3)%7=9%7=星期二
       2102年3月1日星期几=(21%4*5+2/4*5+2%4+3)%7=(5+0+2+3)%7=10%7=星期三
       2103年3月1日星期几=(21%4*5+3/4*5+3%4+3)%7=(5+0+3+3)%7=11%7=星期四
       2104年3月1日星期几=(21%4*5+4/4*5+4%4+3)%7=(5+1+0+3)%7=9%7=星期二(注意:
2104年是闰年)
       9999年3月1日星期几=(99%4*5+99/4*5+99%4+3)%7=(120+15+3+3)%7=141%7=星期一
   注:按400年一轮回!(400年前是一家)的说法
       1600年,2000年是一样的
       1700年,2100年是一样的
       1800年,2200年是一样的
       1900年,2300年是一样的
       所以,万年历实际上是骗人的,应该叫“四百年历”才是。万只是多的意思罢了。
5. 万年某日星期算法  
   公式:某日星期几=(百年%4*5天+年+年/4+月星期表+日+2天)%7
   通同星期偏差表
   闰年  1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
   天数   31  29  31  30  31  30  31  31  30  31   30   31
   星期   3   6   0   3   5   1   3   6   2   4    0    2
   平年  1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
   天数   31  28  31  30  31  30  31  31  30  31   30   31
   星期   4   0   0   3   5   1   3   6   2   4    0    2



可以看出:
月星期表实际是根据(闰年/平年,天数)得到星期数的。
它实际是个固定的数,只要分清闰年/平年即可。

新算法:星期=(百年%4*5+年+年/4+(13*月+8)/5+日)%7
旧算法:星期=(百年%4*5天+年+年/4+月星期表+日+2天)%7

不同之处为月星期表+2天 和 (13*月+8)/5

例如:
3月时,星期表+2天=0+2=2
      (13*月+8)/5=(13*3+8)/5=47/5=9--->2

12月时,星期表+2天=2+2=4
      (13*月+8)/5=(13*12+8)/5=164/5=32--->4

注意下面有差异:

1月时, 闰年星期表+2天=3+2=5
        平年星期表+2天=4+2=6
      (13*月+8)/5=(13*5+8)/5=73/5=14--->0(5月表+2)
2月时, 闰年星期表+2天=6+2=8--->1
        平年星期表+2天=0+2=2
      (13*月+8)/5=(13*6+8)/5=86/5=17--->3(6月表+2)

新算法的1月2月的年被认为的改变为"去年"
y--;//1月2月的年为"去年"

具体推导过程早忘了,我要找找,估计原稿早丢了,因为我以前
都是随手发帖,但绝对是“原创”.
不信可以搜索“13*月+8”,很难发现正解。

总之这个算法抛弃了“闰年/闰月”,以3月为基月,这样排列
的“一年”将是“固定的”,这是“最后一天”不同,即2月的
28日或29日。

故也给公式法提供了方便。

旧算法是我在立交桥下等人用手机导出的。(当时做过几次修改,而且是对的)

新算法是想抛弃月星期表推导出来的。

这些都是想完成小时玩星期转盘自己推导星期算法的一个心愿~~~

世界真奇妙~~~俺从未知道有“蔡勒公式”~~~

但想法都是一样~~~以三月为基月!!!

下面是我刚搜索到的链接!!!

刚仔细研究了“蔡勒公式”,虽然雷同"某年的1、2月要看作上一年的13、14月來計算"

但差异在我把“某年的1、2月要看作上一年的5、6月來計算”

所以“蔡勒公式”的程序应该为:

/*----------------------------------------------------------------------------------------
                                0000年~9999年星期算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDow(unsigned int y, unsigned int m, unsigned int d)
{
unsigned int w, c;
  if (m <= 2)
  {
    m += 12;//1月2月同13月14月表
    y--;//1月2月的年为"去年"
  }
  c = y / 100;
  c &= 0x03;//百年%4
  y %= 100;
//(星期=百年%4-2*百年+年+年/4+26*(月+1)/10+日-1)%7,特别注意1月2月的年为"去年"
  w = (((c << 2)-2*c) + (y + (y >> 2)) + 26*(m + 1)/10 + d-1) % 7;
  return w;//返回星期
}

哈哈~~~农民就是农民,菜农的“农历”上不了"大席面"。

自己玩玩,乐乐。

俺的好些和别人的“雷同”的玩意多了~~~

但26与13,10和5,去年等关键的地方太雷同了~~~

俺感到“知音”还是不少的~~~

相关链接:http://zh.wikipedia.org/wiki/%E6%98%9F%E6%9C%9F%E7%9A%84%E8%A8%88%E7%AE%97

使用特权

评论回复
板凳
wsl_5631|  楼主 | 2008-8-14 16:59 | 只看该作者

沉下来了 顶起来

使用特权

评论回复
地板
delin17| | 2008-8-14 17:22 | 只看该作者

f

呵,算起来确实不对
个人觉得,闰年好像和世纪没关系吧

使用特权

评论回复
5
hotpower| | 2008-8-14 20:19 | 只看该作者

这个算法早已不用,新算法不用查表,基月为三月

我记得2004年我写了至少8个版本~~~让楼主遇到淘汰的了~~~

不需考虑闰年校验的星期算法
http://blog.**/hotpower/158297/message.aspx


/*----------------------------------------------------------------------------------------
                                0000年~9999年星期算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDow(unsigned int y, unsigned int m, unsigned int d)
{
unsigned int w, c;
  if (m <= 2){
    m |= 4;//1月2月同5月六月表
    y--;
  }
  c = y / 100;
  c &= 0x03;//百年%4
  y %= 100;
  w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7
  return w;//返回星期
}

/*----------------------------------------------------------------------------------------
                                0000年~9999年月最大天数算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDom(unsigned int y, unsigned int m)
{
unsigned int dn;
  dn = GetDow(y, m + 1, 1) - GetDow(y, m, 1);//m+1=13表示明年的1月
  if (dn >= 0x80) dn += 7;
  return dn + 28;//返回当月的最大天数
}

使用特权

评论回复
6
aihe| | 2008-8-14 20:46 | 只看该作者

欢迎老HOT回归

使用特权

评论回复
7
wsl_5631|  楼主 | 2008-8-15 09:51 | 只看该作者

谢谢!!

新算法怎么推导?

使用特权

评论回复
8
hotpower| | 2008-8-15 15:24 | 只看该作者

推导还是应该**3月为基月的原则

使用特权

评论回复
9
hotpower| | 2008-8-15 18:11 | 只看该作者

对3月为基月星期算法的验证

这是我在GPS中的星期算法应用源程序
/*----------------------------------------------------------------------------------------
                                0000年~9999年星期算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDow(unsigned int y, unsigned int m, unsigned int d)
{
unsigned int w, c;
  if (m <= 2)
  {
    m |= 4;//1月2月同5月六月表
    y--;//1月2月的年为"去年"
//若年不为0年时,下列4行可不要
    if (y >= 0x8000)//负数
    {
      y = 399;//上个4百年的最后1年
    }
  }
  c = y / 100;
  c &= 0x03;//百年%4
  y %= 100;
//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7,特别注意1月2月的年为"去年"
  w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;
  return w;//返回星期
}

/*----------------------------------------------------------------------------------------
                                0000年~9999年月最大天数算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDom(unsigned int y, unsigned int m)
{
unsigned int dn;
  dn = GetDow(y, m + 1, 1) - GetDow(y, m, 1);//m+1=13表示明年的1月
  if (dn >= 0x8000)//负数
  {
    dn += 7;
  }
  return dn + 28;//返回当月的最大天数
}



下列是刚验证通过的:
int main (void) 
{
volatile unsigned int week;
volatile unsigned int day;

  day  = Rtc.GetDom(   0, 2);   //   0.02    29天(闰年)
  day  = Rtc.GetDom(   1, 2);   //   1.02    28天(平年)
  day  = Rtc.GetDom(   2, 2);   //   2.02    28天(平年)
  day  = Rtc.GetDom(   3, 2);   //   3.02    28天(平年)
  day  = Rtc.GetDom(   4, 2);   //   4.02    29天(闰年)
  day  = Rtc.GetDom( 100, 2);   // 100.02    28天(平年)
  day  = Rtc.GetDom( 200, 2);   // 200.02    28天(平年)
  day  = Rtc.GetDom( 300, 2);   // 300.02    28天(平年)
  day  = Rtc.GetDom( 400, 2);   // 400.02    29天(闰年)
  day  = Rtc.GetDom( 401, 2);   // 401.02    28天(平年)
  day  = Rtc.GetDom( 500, 2);   // 500.02    28天(平年)
  day  = Rtc.GetDom( 600, 2);   // 600.02    28天(平年)
  day  = Rtc.GetDom( 700, 2);   // 700.02    28天(平年)
  day  = Rtc.GetDom( 800, 2);   // 800.02    29天(闰年)

  week = Rtc.GetDow(1999, 1, 1);//1999.01.01 星期五
  week = Rtc.GetDow(1999, 2, 1);//1999.02.01 星期一
  week = Rtc.GetDow(1999, 3, 1);//1999.03.01 星期一

  day  = Rtc.GetDom(1999, 2);   //1999.02    28天(平年)

  week = Rtc.GetDow(2000, 1, 1);//2000.01.01 星期六
  week = Rtc.GetDow(2000, 2, 1);//2000.02.01 星期二
  week = Rtc.GetDow(2000, 3, 1);//2000.03.01 星期三

  day  = Rtc.GetDom(2000, 2);   //2000.02    29天(闰年)

  week = Rtc.GetDow(2001, 1, 1);//2001.01.01 星期一
  week = Rtc.GetDow(2001, 2, 1);//2001.02.01 星期四
  week = Rtc.GetDow(2001, 3, 1);//2001.03.01 星期四

  day  = Rtc.GetDom(2001, 2);   //2001.02    28天(平年)


  week = Rtc.GetDow(2007, 1, 1);//2007.01.01 星期一
  week = Rtc.GetDow(2007, 2, 1);//2007.02.01 星期四
  week = Rtc.GetDow(2007, 3, 1);//2007.03.01 星期四

  day  = Rtc.GetDom(2007, 1);   //2007.01    31天
  day  = Rtc.GetDom(2007, 2);   //2007.02    28天(平年)
  day  = Rtc.GetDom(2007, 3);   //2007.03    31天
  day  = Rtc.GetDom(2007, 4);   //2007.04    30天
  day  = Rtc.GetDom(2007, 5);   //2007.05    31天
  day  = Rtc.GetDom(2007, 6);   //2007.06    30天
  day  = Rtc.GetDom(2007, 7);   //2007.07    31天
  day  = Rtc.GetDom(2007, 8);   //2007.08    31天
  day  = Rtc.GetDom(2007, 9);   //2007.09    30天
  day  = Rtc.GetDom(2007, 10);  //2007.10    31天
  day  = Rtc.GetDom(2007, 11);  //2007.11    30天
  day  = Rtc.GetDom(2007, 12);  //2007.12    31天

  week = Rtc.GetDow(2008, 1, 1);//2008.01.01 星期二
  week = Rtc.GetDow(2008, 2, 1);//2008.02.01 星期五
  week = Rtc.GetDow(2008, 3, 1);//2008.03.01 星期六

  week = Rtc.GetDow(2008, 8, 8);//2008.08.08 星期五
  week = Rtc.GetDow(2008, 8,15);//2008.08.15 星期五(今天)
  week = Rtc.GetDow(2008, 8,16);//2008.08.16 星期六

  day  = Rtc.GetDom(2008, 1);   //2008.01    31天
  day  = Rtc.GetDom(2008, 2);   //2008.02    29天(闰年)
  day  = Rtc.GetDom(2008, 3);   //2008.03    31天
  day  = Rtc.GetDom(2008, 4);   //2008.04    30天
  day  = Rtc.GetDom(2008, 5);   //2008.05    31天
  day  = Rtc.GetDom(2008, 6);   //2008.06    30天
  day  = Rtc.GetDom(2008, 7);   //2008.07    31天
  day  = Rtc.GetDom(2008, 8);   //2008.08    31天
  day  = Rtc.GetDom(2008, 9);   //2008.09    30天
  day  = Rtc.GetDom(2008, 10);  //2008.10    31天
  day  = Rtc.GetDom(2008, 11);  //2008.11    30天
  day  = Rtc.GetDom(2008, 12);  //2008.12    31天

  week = Rtc.GetDow(2009, 1, 1);//2009.01.01 星期四
  week = Rtc.GetDow(2009, 2, 1);//2009.02.01 星期天
  week = Rtc.GetDow(2009, 3, 1);//2009.04.01 星期天

  day  = Rtc.GetDom(2009, 2);   //2009.02    28天(平年)

  week = Rtc.GetDow(2100, 1, 1);//2100.01.01 星期五
  week = Rtc.GetDow(2100, 2, 1);//2100.02.01 星期一
  week = Rtc.GetDow(2100, 3, 1);//2100.03.01 星期一

  day  = Rtc.GetDom(2100, 2);    //2100.02    28天(平年)

  week = Rtc.GetDow(2200, 1, 1);//2200.01.01 星期三
  week = Rtc.GetDow(2200, 2, 1);//2200.02.01 星期六
  week = Rtc.GetDow(2200, 3, 1);//2200.03.01 星期六

  day  = Rtc.GetDom(2200, 2);    //2200.02    28天(平年)

  week = Rtc.GetDow(2300, 1, 1);//2300.01.01 星期一
  week = Rtc.GetDow(2300, 2, 1);//2300.01.01 星期四
  week = Rtc.GetDow(2300, 3, 1);//2300.01.01 星期四

  day  = Rtc.GetDom(2300, 2);   //2300.02    28天(平年)

  week = Rtc.GetDow(2400, 1, 1);//2400.01.01 星期六
  week = Rtc.GetDow(2400, 2, 1);//2400.02.01 星期二
  week = Rtc.GetDow(2400, 3, 1);//2400.03.01 星期三

  day  = Rtc.GetDom(2400, 2);   //2400.02    29天(闰年)

  os_sys_init (MainTask);//启动ARTX,此函数并不返回main()
}

使用特权

评论回复
10
gyt| | 2008-8-16 12:03 | 只看该作者

学习学习

使用特权

评论回复
11
wsl_5631|  楼主 | 2008-8-16 13:07 | 只看该作者

谢谢!

使用特权

评论回复
12
jfzd| | 2008-9-3 23:46 | 只看该作者

似乎之前查表的方法有误啊

刚验证了一下,之前查表的程序,08年8月31日星期天没错,08年9月1日返回也是星期天,不信可以试试,hotpower后面给出的粗略验证了一下,好像没什么问题。
感谢hotpower把好东西拿出来分享,问一下,后面这个公式是自己推导出来的吗?如果是那太厉害了。

使用特权

评论回复
13
懒人| | 2008-9-6 14:09 | 只看该作者

up 学习

使用特权

评论回复
14
hotpower| | 2008-9-6 17:18 | 只看该作者

又搜索到一条更具体的蔡勒公式

蔡勒(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

公式中的符号含义如下:
w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六
c:世纪-1(前两位数)
y:年(后两位数)
m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)
d:日
[ ]代表取整,即只要整数部分。

下面以中华人民共和国成立100周年纪念日那天(2049年10月1日)来计算是星期几,过程如下: 
w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 
=49+[49/4]+[20/4]-2×20+[26×(10+1)/10]+1-1 
=49+[12.25]+5-40+[28.6] 
=49+12+5-40+28 
=54 (除以7余5) 
即2049年10月1日(100周年国庆)是星期五。

再比如计算2006年4月4日,过程如下:
w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 
=6+[6/4]+[20/4]-2*20+[26*(4+1)/10]+4-1
=-12 (除以7余2,注意对负数的取模运算!)

不过,以上的公式都只适合于1582年(我国明朝万历十年)10月15日之后的情形。罗马教皇格里高利十三世在1582年组织了一批天文学家,根据哥白尼日心说计算出来的数据,对儒略历作了修改。将1582年10月5日到14日之间的10天宣布撤销,继10月4日之后为10月15日。
后来人们将这一新的历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历或公历。 


哈哈~~~村里“交通不便”~~~竟然不知早有蔡勒公式~~~

菜农“雷同”的不错~~~


相关链接:http://baike.baidu.com/view/598757.htm

使用特权

评论回复
15
linqing171| | 2008-9-6 18:12 | 只看该作者

这个公式在初中就见过,但是当时不知其所以然。

后来,高中毕业,大学未开学的那两个月里,按照家里的要求,学习了奇门遁甲和摆九宫八卦阵。
从甲己还生甲,已庚丙做初 开始背。
后来对于历法恍然大悟了。
原来二十四节气是跟着阳历走的,农历赶阳历赶不上的时候如果哪个月里有节没有气(一年如果360天,肯定不够24个节气对应的365.2425天,时间长了,总有一个月没有),结果就会闰月。而且农历的闰月的算法及其复杂,口诀被的人都累死,最后发现,原来就是这么回事情。


老hot大叔如果想开发个农历的万年历,可以先看看奇门遁甲啊,里面的公式好用的。

使用特权

评论回复
16
hotpower| | 2008-9-6 19:09 | 只看该作者

真不明白蔡勒公式里的-2c是什么意思

蔡勒公式里的-2c是什么意思???
这样做导致了计算结果负数的出现~~~

下面以中华人民共和国成立100周年纪念日那天(2049年10月1日)来计算是星期几,过程如下: 
w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 
=49+[49/4]+[20/4]-2×20+[26×(10+1)/10]+1-1 
=49+[12.25]+5-40+[28.6] 
=49+12+5-40+28 
=54 (除以7余5) 
即2049年10月1日(100周年国庆)是星期五。

再比如计算2006年4月4日,过程如下:
w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 
=6+[6/4]+[20/4]-2*20+[26*(4+1)/10]+4-1
=-12 (除以7余2,注意对负数的取模运算!)

实在不解-2c是如何推导出来的~~~很是郁闷~~~

不知和下列文字有关???1582年和-2c能扯上关系吗???

不过,以上的公式都只适合于1582年(我国明朝万历十年)10月15日之后的情形。罗马教皇格里高利十三世在1582年组织了一批天文学家,根据哥白尼日心说计算出来的数据,对儒略历作了修改。将1582年10月5日到14日之间的10天宣布撤销,继10月4日之后为10月15日。
后来人们将这一新的历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历或公历。 


相关链接:http://blog.**/hotpower/158250/message.aspx

使用特权

评论回复
17
xwj| | 2008-9-6 19:39 | 只看该作者

实际上是+ (-7/4)c

注意:是 +[c/4]-2c


也就是每4个世纪星期数-1

使用特权

评论回复
18
xwj| | 2008-9-6 19:56 | 只看该作者

典型的1阶比例计算,公式可以这样简化:

蔡勒公式如下:
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

w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
-->>
w=(5/4)y -(7/4)c +(26/10)m +26/10 +d -1
-->>
w=(5/4)y -(7/4)c  +d +(26/10)m +16/10
-->>
w=(5/4)y -(7/4)c  +d +(26m+16)/10

-->>
w=(5/4)y -(7/4)c  +d +(26m+16)/10 +N个7

“N个7” 为保证数值范围的常数,N 为任意正负整数,可以调整后去合适的值以保证数值范围适合机器计算。


也就是说做3个乘除法和对应的加法即可算出


使用特权

评论回复
19
xwj| | 2008-9-6 20:12 | 只看该作者

考虑取值范围,为了避免溢出,机器最后可以这样计算:

w=y +y/4 -c*7/4  +d +(13*m+8)/5 +N个7

由于20xx年正好c/4=0,c*7/4为7的倍数,因此现在做的万年历完全可以从2000年或1600年开始计算,也就是每400年的星期数是完全重合的。

所以,公式也可以这样算:

w=y +y/4 -(c-20)*7/4  +d +(13*m+8)/5

每一项都是正整数,都不超过256。
注意:余数要丢掉!

使用特权

评论回复
20
xwj| | 2008-9-6 20:14 | 只看该作者

呵呵,最后与hot老的公式殊途同归:-)

 w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;

使用特权

评论回复
下一页 »
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

335

帖子

2

粉丝
关闭 热门推荐
快速回复 在线客服 返回列表 返回顶部