欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++算法系列之日歷生成的算法代碼

 更新時(shí)間:2018年05月09日 09:11:35   作者:吹泡泡的小貓  
日歷算法首先要知道日歷的編排規(guī)則,也就是歷法。所謂歷法,指的就是推算年、月、日的時(shí)間長(zhǎng)度和它們之間的關(guān)系,指定時(shí)間序列的法則。

日歷在我們的生活中扮演著十分重要的角色,上班、上學(xué)、約會(huì)都離不開(kāi)日歷。每年新年開(kāi)始,人們都要更換新的日歷,你想知道未來(lái)一年的這么多天是怎么被確定下來(lái)的嗎?為什么去年的國(guó)慶節(jié)是星期五而今年的國(guó)慶節(jié)是星期三?那就來(lái)研究一下日歷算法吧。本文將介紹日歷的編排規(guī)則,確定某日是星期幾的計(jì)算方法,以及如何在計(jì)算機(jī)上打印某一年的年歷。

要研究日歷算法,首先要知道日歷的編排規(guī)則,也就是歷法。所謂歷法,指的就是推算年、月、日的時(shí)間長(zhǎng)度和它們之間的關(guān)系,指定時(shí)間序列的法則。我國(guó)的官方歷法是中國(guó)公歷,也就是世界通用的格里歷(Gregorian Calendar),中國(guó)公歷的年分為平常年和閏年,平常年一年是365天,閏年一年是366天。判定一年是平常年還是閏年的規(guī)則如下:

1、  如果年份是4的倍數(shù),且不是100的倍數(shù),則是閏年;

2、  如果年份是400的倍數(shù),則是閏年;

3、  不滿足1、2條件的就是平常年。

總結(jié)成一句話就是:四年一閏,百年不閏,四百年再閏。

中國(guó)公歷關(guān)于月的規(guī)則是這樣的,一年分為十二個(gè)月,其中一月、三月、五月、七月、八月、十月和十二月是大月,一個(gè)月有31天。四月、六月、九月和十一月是小月,一個(gè)月有30天。二月天數(shù)要根據(jù)是否是閏年來(lái)定,如果是閏年,二月是29天,如果是平常年,二月是28天。

除了年月日,人們?nèi)粘I钪羞€對(duì)日期定義了另一個(gè)屬性,就是星期幾。星期并不是公歷范疇內(nèi)的東西,但是人們已經(jīng)習(xí)慣用星期來(lái)管理和規(guī)劃時(shí)間,比如一個(gè)星期工作五天,休息兩天等等,星期的規(guī)則徹底改變了人們的生活習(xí)慣,因此星期已經(jīng)成為歷法中的一部分了。星期的命名最早起源于古巴比倫文化。公元前7-6世紀(jì),巴比倫人就使用了星期制,一個(gè)星期中的每一天都有一個(gè)天神掌管。這一規(guī)則后來(lái)傳到古羅馬,并逐漸演變成現(xiàn)在的星期制度。

如何知道某一天到底是星期幾?除了查日歷之外,是否有辦法推算出來(lái)某一天是星期幾呢?答案是肯定的,星期不象年和月那樣有固定的歷法規(guī)則,但是星期的計(jì)算也有自己的規(guī)律。星期是固定的7天周期,其排列順序固定,不隨閏年、平常年以及大小月的天數(shù)變化影響。因此,只要確切地知道某一天是星期幾,就可以推算出其它日期是星期幾。推算的方法很簡(jiǎn)單,就是計(jì)算兩個(gè)日期之間相差多少天,用相差的天數(shù)對(duì)7取余數(shù),這個(gè)余數(shù)就是兩個(gè)日期的星期數(shù)的差值。舉個(gè)例子,假設(shè)已經(jīng)知道1977年3月27日是星期日,如何得知1978年3月27日是星期幾?按照前面的方法,計(jì)算出1977年3月27日到1978年3月27日之間相差365天,365除以7余數(shù)是1,所以1978年3月27日就是星期一。

上述方法計(jì)算星期幾的關(guān)鍵是求出兩個(gè)日期之間相隔的天數(shù)。有兩種常用的方法計(jì)算兩個(gè)日期之間相隔的天數(shù),一種是利用公歷的月和年的規(guī)則直接計(jì)算,另一種是利用儒略日計(jì)算。利用公歷規(guī)則直接計(jì)算兩個(gè)日期之間相差的天數(shù),簡(jiǎn)單地講就是將兩個(gè)日期之間相隔的天數(shù)分成三個(gè)部分:前一個(gè)日期所在年份還剩下的天數(shù)、兩個(gè)日期之間相隔的整數(shù)年所包含的天數(shù)和后一個(gè)日期所在的年過(guò)去的天數(shù)。如果兩個(gè)日期是相鄰兩個(gè)年份的日期,則第二部分整年的天數(shù)就是0。以1977年3月27日到2005年5月31日為例,1977年還剩下的天數(shù)是279天,中間整數(shù)年是從1978年到2005年(不包括2005年),共26年,包括7個(gè)閏年和20個(gè)平常年,總計(jì)9862天,最后是2005年從1月1日到5月31日經(jīng)過(guò)的天數(shù)151天。三者總結(jié)10292天。直接利用公歷規(guī)則計(jì)算日期相差天數(shù)的算法實(shí)現(xiàn)如下(為了簡(jiǎn)化算法復(fù)雜度,這個(gè)實(shí)現(xiàn)假設(shè)用于定位星期的那個(gè)日期總是在需要計(jì)算星期幾的那個(gè)日期之前):

int CalculateDays(int ys, int ms, int ds, int ye, int me, int de)
 {
 int days = CalcYearRestDays(ys, ms, ds);
 if(ys != ye) /*不是同一年的日期*/
 {
 if((ye - ys) >= 2) /*間隔超過(guò)一年,要計(jì)算間隔的整年時(shí)間*/
 {
 days += CalcYearsDays(ys + 1, ye);
 }
 days += CalcYearPassedDays(ye, me, de);
 }
 else
 {
 days = days - CalcYearRestDays(ye, me, de);
 }
 return days;
 }
/*計(jì)算一年中過(guò)去的天數(shù),包括指定的這一天*/
 int CalcYearPassedDays(int year, int month, int day)
 {
 int passedDays = 0;
 int i;
 for(i = 0; i < month - 1; i++)
 {
 passedDays += daysOfMonth[i];
 }
 passedDays += day;
 if((month > 2) && IsLeapYear(year))
 passedDays++;
 return passedDays;
 }
/*計(jì)算一年中還剩下的天數(shù),不包括指定的這一天*/
 int CalcYearRestDays(int year, int month, int day)
 {
 int leftDays = daysOfMonth[month - 1] - day;
 int i;
 for(i = month; i < MONTHES_FOR_YEAR; i++)
 {
 leftDays += daysOfMonth[i];
 }
 if((month <= 2) && IsLeapYear(year))
 leftDays++;
 return leftDays;
 }
 
/*
 計(jì)算years年1月1日和yeare年1月1日之間的天數(shù),
 包括years年1月1日,但是不包括yeare年1月1日
 */
 int CalcYearsDays(int years, int yeare)
 {
 int days = 0;
 int i;
 for(i = years; i < yeare; i++)
 {
 if(IsLeapYear(i))
 days += DAYS_OF_LEAP_YEAR;
 else
 days += DAYS_OF_NORMAL_YEAR;
 }
 return days;
 }

另一種計(jì)算兩個(gè)日期相差天數(shù)的方法是利用儒略日(Julian Day,JD)進(jìn)行計(jì)算。首先介紹一下儒略日,儒略日是一種不記年,不記月,只記日的歷法,是由法國(guó)學(xué)者Joseph Justus Scaliger(1540-1609)在1583年提出來(lái)的一種以天數(shù)為計(jì)量單位的流水日歷。儒略日和儒略歷(Julian Calendar)沒(méi)有任何關(guān)系,命名為儒略日也僅僅他本人為了紀(jì)念他的父親――意大利學(xué)者Julius Caesar Scaliger(1484-1558)。簡(jiǎn)單來(lái)講,儒略日就是指從公元前4713年1月1日UTC 12:00開(kāi)始所經(jīng)過(guò)的天數(shù),JD0就被指定為公元前4713年1月1日 12:00到公元前4713年1月2日12:00之間的24小時(shí),依次順推,每一天都被賦予一個(gè)唯一的數(shù)字。例如從1996年1月1日12:00開(kāi)始的一天就是儒略日J(rèn)D2450084。使用儒略日可以把不同歷法的年表統(tǒng)一起來(lái),很方便地在各種歷法中追溯日期。如果計(jì)算兩個(gè)日期之間的天數(shù),利用儒略日計(jì)算也很方便,先計(jì)算出兩個(gè)日期的儒略日數(shù),然后直接相減就可以得到兩個(gè)日期相隔的天數(shù)。

由公歷的日期計(jì)算出儒略日數(shù)是一個(gè)很簡(jiǎn)單的事情,有多個(gè)公式可以計(jì)算儒略日,本文選擇如下公式計(jì)算儒略日:

 

其中y是年份,m是月份,d是日期,如果m小于或等于2,則m修正為m+12,同時(shí)年份修正為y-1。c值由以下方法計(jì)算:

 

下面就是由公歷日期計(jì)算儒略日的算法實(shí)現(xiàn):

int CalculateJulianDay(int year, int month, int day)
{
 int B = 0;
 if(month <= 2)
 {
 month += 12;
 year -= 1;
 }
 if(IsGregorianDays(year, month, day))
 {
 B = year / 100;
 B = 2 - B + year / 400;
 }
 double dd = day + 0.5000115740; /*本日12:00后才是儒略日的開(kāi)始(過(guò)一秒鐘)*/
 return int(365.25 * (year + 4716) + 0.01) + int(30.60001 * (month + 1)) + dd + B - 1524.5;
}

儒略日的計(jì)算通常精確到秒,得到的JD數(shù)也是一個(gè)浮點(diǎn)數(shù),本文僅僅是為了計(jì)算日期相隔的整數(shù)天數(shù),因此都采用整數(shù)計(jì)算。由于儒略日的周期開(kāi)始與每天中午12:00,而歷法中的天數(shù)通常是從0:00開(kāi)始的,因此儒略日計(jì)算上對(duì)日期的天數(shù)進(jìn)行了修正。1977年3月27日的儒略日是2443230,2005年5月31日的儒略日是2453522,差值是10292,和前一種方法計(jì)算的結(jié)果一致。

我們用兩種方法計(jì)算出兩個(gè)日期之間的天數(shù)都是10292,現(xiàn)在用10292除以7得到余數(shù)是2,也就是說(shuō)2005年5月31日與1977年3月27日星期數(shù)差兩天,所以2005年5月31日就是是星期二。

上述計(jì)算星期的方法雖然步驟簡(jiǎn)單,但是每次都要計(jì)算兩個(gè)日期的時(shí)間差,不是非常方便。如果能夠有一個(gè)公式可以直接根據(jù)日期計(jì)算出對(duì)應(yīng)的星期豈不是更好?幸運(yùn)的是,這樣的公式是存在的,下篇將繼續(xù)介紹公式法直接計(jì)算某一天星期數(shù)的算法。

小知識(shí)1:公歷的閏年

中國(guó)公歷(也就是格里歷)的置閏規(guī)則是四年一閏,百年不閏,四百年再閏,為什么會(huì)有這么奇怪的置閏規(guī)則呢?這實(shí)際上與天體運(yùn)行周期與人類定義的歷法周期之間的誤差有關(guān)。地球繞太陽(yáng)運(yùn)轉(zhuǎn)的周期是365.2422天,即一個(gè)回歸年(Tropical Year),而公歷的一年是365天,這樣一年就比回歸年短了0.2422日,四年積累下來(lái)就多出0.9688天(約1天),于是設(shè)置一個(gè)閏年,這一年多一天。這樣一來(lái),四個(gè)公歷年又比四個(gè)回歸年多了0.0312天,平均每年多0.0078天,這樣經(jīng)過(guò)四百年就會(huì)多出3.12天,也就是說(shuō)每四百年要減少3個(gè)閏年才行,于是就設(shè)置了百年不閏,四百年再閏的置閏規(guī)則。

實(shí)際上公歷的置閏還有一條規(guī)則,就是對(duì)于數(shù)值很大的年份,如果能整除3200,同時(shí)能整除172800則是閏年。這是因?yàn)榍懊婕词顾陌倌暌婚c,仍然多了0.12天,平均就是每天多0.0003天,于是每3200年就又多出0.96天,也就是說(shuō)每3200年還要減少一個(gè)閏年,于是能被3200整除的年就不是閏年了。然而誤差并沒(méi)有終結(jié),每3200年減少一個(gè)閏年(減少一天)實(shí)際上多減了0.04天,這個(gè)誤差還要繼續(xù)累計(jì)計(jì)算,這已經(jīng)超出了本文的范圍,有興趣的讀者可以自己計(jì)算。

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • C++子類父類成員函數(shù)的覆蓋和隱藏實(shí)例詳解

    C++子類父類成員函數(shù)的覆蓋和隱藏實(shí)例詳解

    這篇文章主要介紹了C++子類父類成員函數(shù)的覆蓋和隱藏實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++歸并排序算法詳解

    C++歸并排序算法詳解

    大家好,本篇文章主要講的是C++歸并排序算法詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • C/C++后端學(xué)習(xí)與練習(xí)深入

    C/C++后端學(xué)習(xí)與練習(xí)深入

    這篇文章主要介紹了C/C++對(duì)于后端的學(xué)習(xí)與練習(xí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲

    基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲

    這篇文章主要介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲,用到雙向隊(duì)列,方便在運(yùn)行完畢后輸出經(jīng)過(guò)的點(diǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C++ deque/queue/stack的底層原理解析

    C++ deque/queue/stack的底層原理解析

    這篇文章主要介紹了C++ deque/queue/stack的底層原理解析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • C語(yǔ)言表達(dá)式求值中類型轉(zhuǎn)換和優(yōu)先級(jí)等問(wèn)題詳解

    C語(yǔ)言表達(dá)式求值中類型轉(zhuǎn)換和優(yōu)先級(jí)等問(wèn)題詳解

    表達(dá)式求值是一個(gè)常見(jiàn)的問(wèn)題,可以用C語(yǔ)言實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言表達(dá)式求值中類型轉(zhuǎn)換和優(yōu)先級(jí)等問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • C++ STL list 遍歷刪除出錯(cuò)解決方案

    C++ STL list 遍歷刪除出錯(cuò)解決方案

    這篇文章主要介紹了C++ STL list 遍歷刪除出錯(cuò)解決方案的相關(guān)資料,這里對(duì)出錯(cuò)進(jìn)行分析,并給出正確的解決方法,需要的朋友可以參考下
    2016-12-12
  • C語(yǔ)言qsort()函數(shù)的使用方法詳解

    C語(yǔ)言qsort()函數(shù)的使用方法詳解

    qsort是一個(gè)庫(kù)函數(shù),基于快速排序算法實(shí)現(xiàn)的一個(gè)排序的函數(shù),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言qsort()函數(shù)使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • c語(yǔ)言獲取當(dāng)前工作路徑的實(shí)現(xiàn)代碼(windows/linux)

    c語(yǔ)言獲取當(dāng)前工作路徑的實(shí)現(xiàn)代碼(windows/linux)

    這篇文章主要介紹了c語(yǔ)言獲取當(dāng)前工作路徑的實(shí)現(xiàn)代碼(windows/linux),需要的朋友可以參考下
    2017-09-09
  • C++中std::is_object的具體使用

    C++中std::is_object的具體使用

    std::is_object是一種C++類型特性,其用途是判斷一個(gè)類型是否是一個(gè)對(duì)象類型,本文主要介紹了C++中std::is_object的具體使用,感興趣的可以了解一下
    2024-01-01

最新評(píng)論