最近有網友在微博上向我反映,《演算法的樂趣》隨書的例子**中關於農曆曆法的演示程式出了bug,並截了圖給我,我開始以為是演算法中的某些部分不相容64位系統,後來發現在32位系統上一樣有問題,什麼問題呢?先看看截圖:
看到了吧,「三十月大」,走查**,發現是處理農曆閏月的時候重拍月序關係,導致越界訪問了。對了一下曆法,2023年不是閏年,怎麼會走到閏月處理的流程中去了呢?
跟了一下**,終於找到原因了,原來是「民間曆法」和「歷理曆法」的差異搗的鬼。先複習一下《 演算法系列之二十:計算中國農曆(二) 》中關於「民間曆法」和「歷理曆法」的小知識:
新中國成立以後沒有頒布新的「官方農曆曆法」,將曆法和政治分離體現了時代的進步,但是由於沒有 「官方曆法」,也引起了一些問題。比如我國現在採用的農曆曆法是《時憲曆》,它源於清朝順治年間(公元1645)頒布的《順治歷》,它有兩個不足之處:乙個是日月合朔和節氣的時間以北京當地時間為準,也就是東經116度25分的當地時間,其節氣和新月的觀察只適用於中原地區。其它經度的地方,因為時間的關係,對導致日月合朔和節氣時間的差異導致置閏和月順序各不相同。另乙個不足之處就是日月合朔時間和節氣時間判斷不精確,如果日月合朔時間和節氣時間在同一天,不管具體的時間是否有先後,一律將此節氣算做新月中的節氣,這樣一來,如果這個節氣是中氣,就會影響到閏月的設定。歷理曆法針對這兩點進行了改進,對節氣時間和日月合朔時間統一採用東經120度即東八區標準時,這樣在任何時區的節氣和置閏結果都是一樣的,以東八區標準時為準。對於節氣時間和日月合朔時間在同一天的情況,精確計算到時、分、秒,只有日月合朔時間在節氣時間之前,這個節氣才包含在次月內。歷理曆法從理論上講更符合現代天文學的精確計算,但是需要注意的是,歷理曆法仍然只是存在於理論上的曆法,我國現行的農曆曆法依然是民間曆法《時憲曆》或《順治歷》。對比一下計算得到的儒略日,2023年的冬至節氣是2023年12月22日 07時02分,2023年農曆冬月(十一月)初一剛好也是這一天,具體時間是2023年12月22日 09時35分。如果嚴格按照歷理曆法,這個冬月的朔日應該算在2023年農曆年中,也就是說,2023年應該是閏年(2023年冬至是2023年12月22日12時47分,兩個冬至節氣之間有13個朔日)。但是實際曆法是2023年是閏年,因為我們目前仍然採用的是民間曆法,當節氣和朔日在同一天時,不管實際的先後順序,一律將此節氣算作此農曆月的中氣,實際上就把這個農曆月劃到了2023年,這樣以來,2023年就多了乙個朔望月,自然就在2023年置閏了,2023年就不應該是閏年了。
隨書給出的演算法簡單地按照歷理曆法計算閏年,將2023年12月22日 09時35分這個新月算作2023年,剛好這個月沒有中氣(冬至就是中氣,但是因為早了2個小時,就被算作上個月的節氣了),於是就按照規則置閏,於是就越界了。
知道問題原因了,解決方法就簡單了。要麼仍然按照歷理曆法處理,只需要解決置閏演算法部分的異常,解決越界問題就行了。要麼按照民間曆法來,當冬至和朔日是同一天時,無論實際的時間先後,都將冬至節氣算作這個月的中氣。
第一章 關於linux的歷史
很多關於linux的書籍在前面章節中寫了一大堆東西來介紹linux,可惜讀者看了好久也沒有正式開始進入linux的世界,這樣反而導致了他們對linux失去了一些興趣,而把厚厚的一本書丟掉。linux的歷史確實有必要讓讀者了解的,但是不了解也並不會影響你將來的linux技術水平。哈哈,本人其實就不怎麼...
第一章 簡單的順序程式
1.1 a b問題 小朋友 include int main 犇犇 include int main 1.2 比較char型的ascii碼大小 小朋友 include int main else return 0 犇犇 include int main 1.3 有關四則運算的練習 小朋友 inclu...
第一章實驗 簡單的C 程式
實驗目的和要求 1.熟悉code blocks 16.01編譯系統的常用功能。2.學會使用code blocks 16.01編譯系統實驗的c 程式。3.熟悉c 程式的基本結構,學會使用簡單的輸入 輸出操作。實驗內容 1.編譯下列程式,改正所出現的錯誤資訊,並寫出輸出結果。執行結果如下 修改程式如下 ...