一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++算法系列之日歷生成的算法代碼

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

2021-06-25 15:19吹泡泡的小貓 C/C++

日歷算法首先要知道日歷的編排規則,也就是歷法。所謂歷法,指的就是推算年、月、日的時間長度和它們之間的關系,指定時間序列的法則。

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

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

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

2、  如果年份是400的倍數,則是閏年;

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

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

中國公歷關于月的規則是這樣的,一年分為十二個月,其中一月、三月、五月、七月、八月、十月和十二月是大月,一個月有31天。四月、六月、九月和十一月是小月,一個月有30天。二月天數要根據是否是閏年來定,如果是閏年,二月是29天,如果是平常年,二月是28天。

除了年月日,人們日常生活中還對日期定義了另一個屬性,就是星期幾。星期并不是公歷范疇內的東西,但是人們已經習慣用星期來管理和規劃時間,比如一個星期工作五天,休息兩天等等,星期的規則徹底改變了人們的生活習慣,因此星期已經成為歷法中的一部分了。星期的命名最早起源于古巴比倫文化。公元前7-6世紀,巴比倫人就使用了星期制,一個星期中的每一天都有一個天神掌管。這一規則后來傳到古羅馬,并逐漸演變成現在的星期制度。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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) /*間隔超過一年,要計算間隔的整年時間*/
 {
 days += CalcYearsDays(ys + 1, ye);
 }
 days += CalcYearPassedDays(ye, me, de);
 }
 else
 {
 days = days - CalcYearRestDays(ye, me, de);
 }
 return days;
 }
/*計算一年中過去的天數,包括指定的這一天*/
 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;
 }
/*計算一年中還剩下的天數,不包括指定的這一天*/
 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;
 }
 
/*
 計算years年1月1日和yeare年1月1日之間的天數,
 包括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;
 }

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

由公歷的日期計算出儒略日數是一個很簡單的事情,有多個公式可以計算儒略日,本文選擇如下公式計算儒略日:

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

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

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

下面就是由公歷日期計算儒略日的算法實現:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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后才是儒略日的開始(過一秒鐘)*/
 return int(365.25 * (year + 4716) + 0.01) + int(30.60001 * (month + 1)) + dd + B - 1524.5;
}

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

我們用兩種方法計算出兩個日期之間的天數都是10292,現在用10292除以7得到余數是2,也就是說2005年5月31日與1977年3月27日星期數差兩天,所以2005年5月31日就是是星期二。

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

小知識1:公歷的閏年

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

實際上公歷的置閏還有一條規則,就是對于數值很大的年份,如果能整除3200,同時能整除172800則是閏年。這是因為前面即使四百年一閏,仍然多了0.12天,平均就是每天多0.0003天,于是每3200年就又多出0.96天,也就是說每3200年還要減少一個閏年,于是能被3200整除的年就不是閏年了。然而誤差并沒有終結,每3200年減少一個閏年(減少一天)實際上多減了0.04天,這個誤差還要繼續累計計算,這已經超出了本文的范圍,有興趣的讀者可以自己計算。

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://blog.csdn.net/orbit/article/details/7749723

延伸 · 閱讀

精彩推薦
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
主站蜘蛛池模板: 丰满大乳欲妇三级k8 | china精品对白普通话 | 午夜一级视频 | 13 sewang41| 秋霞一级毛片 | 丰满大屁股美女一级毛片 | 国产精品嫩草影院一二三区入口 | 红色播放器 | 欧美一区二区三区精品影视 | 色综合久久丁香婷婷 | 国产一区二区在线观看视频 | 四虎最新紧急更新地址 | 天堂在线中文字幕 | 天码毛片一区二区三区入口 | 日韩欧美一区二区三区免费观看 | 亚洲欧美精品一区天堂久久 | 精品国产免费第一区二区三区日韩 | 99久久精品国产免费 | 99视频久久精品久久 | 青青草99热久久 | 久久精品麻豆国产天美传媒果冻 | chinese男男gayxxx chinese老头和老太交hd | 日韩欧美精品一区二区 | 暴露狂婷婷 | 精品欧美一区二区在线观看欧美熟 | 国产美女在线一区二区三区 | 午夜福利电影网站鲁片大全 | 美女被扣逼 | 香蕉精品国产高清自在自线 | 色综合视频一区二区观看 | 91久久综合九色综合欧美98 | 精品夜夜澡人妻无码AV蜜桃 | 日本无遮挡亲吻膜下面免费 | 日韩精品欧美激情国产一区 | 色综合视频一区二区三区 | 亚洲激情网 | 亚洲乱人伦在线 | 五月天色网站 | 成年视频在线观看免费 | 2020最新韩国理论三级0k | 私人家庭影院5577 |