• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            任我行

            一天一個(gè)腳印......
            每日一句:
            posts - 54, comments - 218, trackbacks - 1, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            星期推算法

            Posted on 2005-10-22 11:50 任我行 閱讀(1540) 評論(0)  編輯 收藏 引用 所屬分類: C++

            通常我們只知道生活當(dāng)天的前后幾天是星期幾,即便是翻日歷,也只能知道有限日期的星期數(shù)。那么有沒有一種方法可以讓我們知道任何一天是星期幾呢?有,下面我將向大家介紹一種方法,用以編寫萬年歷的程序。

            首先我們必須約定一些法則,我們用Y、M、D分別表示年、月、日,用數(shù)字0-6分別表示星期日-星期六,這樣我們就可以開始推導(dǎo)我們的公式了。

            我們知道2002年9月1號為星期日,如果我們要想知道2002年9月10號為星期幾,可以這樣算:(0+(10-1))%7=(0+9)%7=2,即星期二。同樣可算得2002年9月20號為:(0+(20-1))%7=(0+19)%7=5,即星期五。但是這樣算需要把日期減1,不太方便,為了解決這個(gè)問題,我們可以假設(shè)每個(gè)月有一個(gè)0號,由于2002年9月1號為星期日,那么2002年9月0號為星期六,這樣算9月10號,只需代入10既(6+10)%7=2。事實(shí)上,9月0號也就是8月31號,每個(gè)月0號的星期數(shù)實(shí)際上就是每個(gè)月1號的前一天的星期數(shù)。我把這個(gè)星期數(shù)稱之為每個(gè)月的代碼。有了這個(gè)代碼,要算這個(gè)月任一天的星期數(shù)都好辦了。

            以上討論的是一年中每個(gè)月的代碼,事實(shí)上對于每年也有一個(gè)代碼,這個(gè)代碼就是每年1月0號(即1月1號的前一天)的星期數(shù),也就是一月份的代碼。如果我們能夠找到每年的代碼之間的關(guān)系,那么要計(jì)算萬年歷就易如反掌了。

             

            (一)推算年的代碼公式

            我們都知道,平年一年有365天,即52周多1天。閏年為366天即52周多2天。我們先只考慮平年的情況。

            假設(shè)第N年的代碼為W,則第N+1年的代碼為(W+1)%7,而第N+K年的代碼則為(W+K)%7。這是因?yàn)閺牡贜年到第N+K年共經(jīng)過了K年,每過一年也就是過了52周余1天,經(jīng)過K年也就是過了52*K周余K天,將多余的天數(shù)K加上第N年的代碼W再對7取模,所得也就是第N+K年的代碼了。

            下面我們把閏年也考慮進(jìn)來。判斷閏年的規(guī)則是,能被4整除,并能被100和400同時(shí)整除的年份就是閏年。所以從第N年到第N+K年間共有K/4 -K/100+K/400個(gè)閏年,而每個(gè)閏年有52周余2天,要比平年多余了1天,即共多余了K/4-K/100+K/400天。我們應(yīng)該把這些天也加進(jìn)去,所以第N+K年的代碼應(yīng)為(W+K+K/4-K/100+K/400)%7。

            這樣子是不是就考慮完全了呢?并非如此,我們還有兩點(diǎn)沒考慮到。第一點(diǎn)是第N年是不是閏年。如果第N年是閏年的話,它本身就是52周余2天,而我們在上面卻是把它當(dāng)作平年來計(jì)算的,少算了1天,應(yīng)加上。所以在第N年為閏年的時(shí)候上式應(yīng)為(W+(K+1)+K/4-K/100+K/400)%7。第二點(diǎn)是第N+K年是不是閏年。如果第N+K年是閏年,雖然它有52周余2天,但只有在算第N+(K+1)年的時(shí)候,才需要多加它那一天,而在算第N+K年的時(shí)候不需要多加這1天,因此我們必須將上式改為(W+(K+1)+(K-1)/4-(K-1)/100+(K-1)/400)%7(注意千萬不能改為(W+(K+1)+(K/4-K/100+K/400-1))%7=(W+K+K/4-K/100+K/400)%7)。

            由此我們可以得出當(dāng)?shù)贜年為閏年時(shí),第N+K年的代碼計(jì)算式為:

            A=(W+(K+1)+(K-1)/4-(K-1)/100+(K-1)/400)%7為了方便計(jì)算,我們可以取N為0,也就是假設(shè)公元元年的代碼為W。因?yàn)楣暌彩情c年,符合上式,那么當(dāng)我們輸入的年份為Y時(shí),此時(shí)就有K=Y,也就是說第Y年的代碼為

            A=(W+(Y+1)+(Y-1)/4-(Y-1)/100+(Y-1)/400)%7接下來的問題就是W究竟是一個(gè)什么數(shù)了,下面我們就來解決這個(gè)問題。

            我們已經(jīng)知道2002年1月1號為星期二,它的前一天為星期一,那也就是說2002年的代碼就是1,由此我們可得

            (W+(2002+1)+(2002-1)/4-(2002-1)/100+(2002-1)/400)%7=1

            (W+2488)%7=1

            (W+3)%7=1

            這樣我們就可求得W=5。我們的公式就變成了如下形式

            A=(5+(Y+1)+(Y-1)/4-(Y-1)/100+(Y-1)/400)%7有了這個(gè)公式,我們就可以算公元后任意一年的代碼了,但還不能算公元前的,我們還需要再改進(jìn)一下,得出公式(1):

            (1)Ayear= Y>0 ? (5+(Y+1)+(Y-1)/4-(Y-1)/100+(Y-1)/400)%7

            : (5 + Y + Y/4 - Y/100 + Y/400) % 7

            這樣就OK了。不過這又導(dǎo)致了另一個(gè)問題:Y<0時(shí),算得的A有可能小于0。這個(gè)問題我們暫且留下,待會再解決。

             

            (二)推算月的代碼公式

            年的問題解決了,月怎么辦呢?請看下表:

             

            月份

            代碼

            差值

            一月

            A

            0

            二月

            A+3

            3

            三月

            A+3

            3

            四月

            A+6

            6

            五月

            A+1

            1

            六月

            A+4

            4

            七月

            A+6

            6

            八月

            A+2

            2

            九月

            A+5

            5

            十月

            A

            0

            十一月

            A+3

            3

            十二月

            A+5

            5

            表中的A為當(dāng)年的代碼。由這個(gè)表我們可以看出,月與月之間也有一定的關(guān)系。由此我們可以推出下面的公式(2):

            (2)Amonth=M>2 ? (Ayear+2*(M+1)+3*(M+1)/5)%7

            : (Ayear+2*(M+2)+3*(M+2)/5)%7

            但是上表所反映的僅為平年的情況,若Y為閏年,則在M大于2時(shí),每個(gè)月的代碼還需再加1。這可用一個(gè)IF語句解決:

            (3)if (((Y%4==0 && Y%100!==0) || (Y%400==0)) && M > 2)

            Amonth = (Amonth+1)%7;

            現(xiàn)在我們回到公式(1)中的問題。如果Y<0時(shí),使得Ayear<0,那么Ayear最小也只能到-6。大家可以看到,當(dāng)我們將Ayear代入公式(2)時(shí),問題就自然解決了。

             

            (三)計(jì)算日期

            有了上面的公式,當(dāng)我們輸入日期后,就很容易算出當(dāng)天為星期幾了,而且可以計(jì)算變量允許范圍內(nèi)的任意一天的星期數(shù)。

            (4)A = (Amonth+D)%7

            (四)寫程序

            下面給出該萬年歷的程序,約莫估計(jì),它可從公元前數(shù)十億年算到公元后數(shù)十億年(即從負(fù)十位數(shù)到正十位數(shù)),而且無一錯(cuò)漏。

            (程序中并沒有對輸入的月份和日期進(jìn)行出錯(cuò)處理)

            #include <stdio.h>

            char *week[] = {"Sunday",

            "Monday",

            "Tuesday",

            "Wednesday",

            "Thursday",

            "Friday",

            "Saturday"};

            void main()

            {

            int Y;

            int M;

            int D;

            int A;

            printf("
            Enter year:");

            scanf("%d",&Y);

            printf("
            Enter month:");

            scanf("%d",&M);

            printf("
            Enter date:");

            scanf("%d",&D);

            //下面的四條語句用來計(jì)算輸入日期的星期數(shù),是程序的核心部分,缺一不可

            A = Y > 0 ? (5 + (Y + 1) + (Y - 1)/4 - (Y - 1)/100 + (Y - 1)/400) % 7

            : (5 + Y + Y/4 - Y/100 + Y/400) % 7;

             

            A = M > 2 ? (A + 2*(M + 1) + 3*(M + 1)/5) % 7

            : (A + 2*(M + 2) + 3*(M + 2)/5) % 7;

             

            if (((Y%4 == 0 && Y%100 != 0) || Y%400 == 0) && M>2)

            {

            A = (A + 1) % 7;

            }

            A = (A + D) % 7;

            printf("
            I's a %s.

            ",week[A]);

            }
            《轉(zhuǎn)貼》

            国产精品无码久久综合| 久久精品国产色蜜蜜麻豆| 久久99精品久久久久子伦| 日韩精品久久无码人妻中文字幕 | 久久99毛片免费观看不卡| 国产高潮国产高潮久久久| a高清免费毛片久久| 日本加勒比久久精品| 久久久久久伊人高潮影院| 久久r热这里有精品视频| 久久人妻少妇嫩草AV蜜桃| 久久久久久国产精品免费无码 | 婷婷综合久久中文字幕蜜桃三电影| AV无码久久久久不卡蜜桃| 久久国产成人亚洲精品影院| 亚洲精品美女久久久久99| 国产精品女同一区二区久久| 久久99国产精品久久99小说| 久久亚洲国产午夜精品理论片| 亚洲精品成人网久久久久久| 免费观看成人久久网免费观看| 久久人人爽人人爽人人片AV不| 老司机国内精品久久久久| 精品久久久久久久无码| 久久人人爽人人爽人人片AV高清| 久久精品国产99久久香蕉| 97久久精品无码一区二区天美| 97精品依人久久久大香线蕉97 | 亚洲国产精品久久电影欧美| 亚洲v国产v天堂a无码久久| 7国产欧美日韩综合天堂中文久久久久 | 久久66热人妻偷产精品9| 狠狠久久综合| 国产一级做a爰片久久毛片| 色婷婷久久综合中文久久蜜桃av| 久久亚洲AV无码西西人体| 94久久国产乱子伦精品免费| 精品久久一区二区三区| 97久久久久人妻精品专区| 国产一区二区三区久久| 久久国产精品成人免费|