?

古代歷法算法的計算機模擬

2018-06-11 07:53滕艷輝田衛軍王鵬云
文化創新比較研究 2018年13期
關鍵詞:枚舉歷法常數

滕艷輝,田衛軍,王鵬云

(咸陽師范學院 數學與信息科學學院,陜西咸陽 71200)

歷法是中國傳統文化的重要組成部分。歷法在歷史學、地球物理學、天體物理學和考古天文學中發揮了很重要的作用。過去,大批天文史家和歷史學家在古代歷法解讀與算法原理方面做了大量的工作。而要想更全面更直觀的理解中國古代歷法,對歷法的推算過程進行模擬實驗,對推算的結果進行復原是十分必要的。1980年代后,隨著微型電子計算機的普及,歷法研究者開始使用計算機對古代歷法進行模擬和復原。[1-5]但截至目前,這方面的工作還僅是一個開端,較為深入的研究仍很少。本文試圖討論古代歷法計算機模擬的可行性及實施思路和方案。

1 傳統歷法的算法特征

中國傳統歷法不僅僅是給出歷日計算,頒行歷書,它的更重要的作用是推算太陽運動、月亮運動、日月交食、五行運動以及各種天象的發生時間和在天空的位置。傳統歷法的是由天文常數和算法推步構成的,其本質是中國數理天文學。它的每一個推算過程都是是數值算法。每個具體算法都有確定的名稱。每一個推算過程也有明確的目的,并且都能在有限步內完成,得到確定的結果。推算過程中所需要參與運算的各參數要么是歷法給出的天文常數,要么是在前面算法中已經計算出來的結果。

古代歷法中的算法以文字的形式一般描述成 “求……:置……,為……”,如歷法記載“各以入氣、入轉朏朒定數朏減朒加經朔、弦、望小余,滿若不足,進退大余,命甲子,算外,各得定日及余?!盵6]這段術文是《崇天歷》求“朔望定日”(即定朔定望時刻)的術文,所需要的參數是經朔、望小余和入氣、入轉朏朒定數,而這幾個值在此算法之前已經求得,于是該算法就可轉化為公式,并容易得到結果。因此,中國傳統歷法中的算法具有確定性,有窮性和可解性,與現代計算機科學中的算法性質相同。歷法推算中同樣使用的順序、分支和循環的基本算法結構。因此,使用計算機來模擬古代歷法中的算法是可行的。

中國傳統歷法使用的積年數都很大。特別是唐代以后,有的積年數甚至達到幾千萬。這使得歷法推算的工作量非常大。在古代,使用傳統歷法具體推算的工具只有籌算和筆算,可想而知,這樣的工作既耗時又耗力,而且還不能保證在推算中不出現錯誤。如果推算過程某個地方出現錯誤,錯誤出現的地方就非常不易查找,而且查找錯誤所耗的時間精力不亞于重新推算。而具有機械性、高效性和穩定性的電子計算機卻很適合做這樣的工作。

2 歷法計算機模擬的思路

實現歷法計算機模擬主的整體思路是:首先是全面整理古代歷法,對其中的算術文進行??焙褪崂?,并將其中文本形式的常數和表格進行數字化;然后是建立各算法之間的相互關系,確定輸入輸出參數,建立數據流圖,在此基礎上,將歷法中的文字性描述的算法完全公式化,并完成程序流程圖的設計;最后是選擇程序開發工具,編寫具體程序代碼和軟件交互的界面UI設計,并通過程序調試和軟件測試,打包發布可用的古代歷法計算機模擬的軟件。

自漢代至明代,中國一共行用了100多部官方歷法。我們需要根據歷法的術文的完整性進行分類,指出哪些歷法是可以進行模擬的,哪些是不可以的。有30多部傳統歷法的術文是完整的保存至今的。用計算機模擬這些歷法也就相當于在復原古人的計算過程和計算結果。還有30部左右歷法的術文大部分被保留下來,但缺少某些片段,通過對比其它完整歷法,或是根據某些史料記載,如果能夠修補,使之成為完整的歷法,我們也可以模擬其算法和結果。例如,《大衍歷》之后的《至德歷》、《五紀歷》和《正元歷》的術文都沒有被記載下來,但基本常數和表格都是完整,并且史書中記載,這些歷法的算法與《大衍歷》相同。對這些歷法的模擬按照《大衍歷》的算法就行了。其余幾十部歷法,有些僅是記載了少量的天文常數,有的甚至完全失傳了。目前,我們還沒有辦法對這些歷法進行模擬復原。

中國古代數理天文學的基本天文常數是回歸年和朔望月,其它常數都是導出常數,可以使用基本常數進行推算。[7]為了方便具體算法中調用這些天文常數,我們事先將其整理好并進行存儲。我們選擇關系型數據庫來存儲這些數據,每一部歷法單獨建立一個數據庫。每一個數據庫里面建立一個名為“天文常數”的表。這個表將存儲這部歷法推算時用到的所有常數,并將歷法的基本信息也作為記錄存放其中。這個表的各列分別是“id、常數、常數值、備注……”等項目,表的每行就是一個常數的各項值等信息。

中國傳統歷法中還存在著為了計算方便而事先給出的表格。這些表格是為,在具體計算中需要那些數值,直接查表即可。表格主要有日躔表、月離表、七十二候表、赤道宿度表、24氣圭表影長表、五星盈縮歷表、五星段次表等。這些表格我們可以直接作為數據庫的表格存儲,表的名稱、列名都按照歷法給出的名字命名。

還有一些表格不存在于歷法術文中,必須通過歷法已經給出的構造方法建立好了才能進使用。每日日躔表、每日圭表影長表、每日日出分表、每日月亮遲疾表等就屬于此類。這些表格我們也根據歷法給出的表格布局建立相應名稱和結構的表格,然后根據歷法的推算,編寫程序計算出數據,存于相應的表中,方便歷法推步時隨時調用。

此外,歷法為了補充算法或表格而給出的一些獨立數值,這些值雖然比較少,但很零散,如月亮在七日十四日二十一日的月離數據。這些數據我們也單獨建立一個為“輔助表格”的表,根據各部歷法的具體情況定義表格的結構。計算機模擬復原的結果也需要輸出,我們在各歷法的數據庫里也建立了定朔表、太陽運行宿次表、月食表和日食表等表格。

3 古代歷法計算模擬的實施方案

古代歷法算法的計算機模擬是一個相對較小的軟件,我們僅采用軟件工程的思想進行總體設計和詳細設計,沒有必要完全按照工程化的步驟進行。

3.1 面向對象的總體設計

我們擬采用面向對象的程序設計,總體設計包括基本數據類,數據庫操作,歷法推步類和可視化圖形界面設計等。在進行設計之前,我們需要給出算法模擬程序所涉及到的對象、變量以及類型名稱的命名規則。對象的公共變量(屬性)名稱形式是“tc+變量名稱”;對象及其子類名稱形式是“to+對象或子類名稱”;對象的公共函數(方法)名稱形式是“tf_+方法名稱”;枚舉類名稱“tm+枚舉類名”,枚舉值“etm+枚舉文本”;所有名稱的首字母都大寫。

在“基本數據類”中,我們定義了基本運算類、枚舉類和其它一些自定義數據類型?;具\算類定義了歷法推算能用到的數值計算方法,如整數約分、實數取余、格式化數值結果(四舍五入等)和分數的比較等。計算機程序中不能直接將節氣、時辰和干支這些歷法特有的時間作為變量,我們將這些文字項作為枚舉數值類型,使節氣、時辰和干支對應于具體數字。例如干支枚舉的定義如下。

Public Enum tmGanZhi

etmJIAZI=1‘甲子

etmYICHOU=2‘乙丑

……

etmGUIHAI=60‘癸亥

End Enum

時辰枚舉類名是 “tmShiChen”,節氣枚舉類名是”tmJieQi”是定義。枚舉類中,我們還定義了如何取得枚舉記錄的文字項。例如 “Public Function tf_RecGanZhi(ByVal ruqi As tmGanZhi)As String”就是將干支的枚舉值轉換成具體干支文字的方法。

歷法推算的最終結果以及中間計算的有參考意義的結果都放在天文記錄類里定義,其定義如下。

基本推步類是計算機模擬的核心部分。我們設計了氣朔(toQishuo)、日躔(toRichan)、晷漏(toGuilou)、月離(toYueli)、交會(toJiaoshi)和火星(toHuoxing)等幾個子類。傳統歷法有百部之多,行用長達2000年,不同時代和發展階段的歷法,其具體算法肯定會有所不停。在軟件設計時,我們盡量為同一種推算設計通用的算法,能夠使多部歷法公用一個計算機算法。當然,如果不同歷法間的同一推算方法完全不同,我們就為這部歷法單獨設計相應算法,與通用算法放在具體的推步類中。例如,交會類的定義如下。

Public Class toJiaoshi

Public tcJiaozhongf As Double'交終分

……

Public tcJiaoshu As Double‘交數

Public Function tf_GetShishenDy()As Double‘食甚時刻一般算法

Public Function tf_GetShishenDyctl()As Double‘《黃極歷》食甚時刻算法

……

End Class

要說明的是,為了編制數據流圖的方便,我們對每個類型的每個成員都給出一個編碼,加以識別。因計算機模擬程序相對簡單,我們這里同樣不需要按照軟件工程的方法建立數據字典。對對象的編碼加以說明對程序的內容加以注釋就可以了。

建立每一個推步類時,都要先解讀每一個子算法,得到算法的輸入和輸出變量信息;建立整個歷法推步的框架,找到各子算法在這個框架中的位置以及各子算法之間的相互聯系;并明確各常數和算法的現代天文學意義。根據各算法的關系建立數據流圖,完成整體設計。

3.2 詳細設計與代碼編寫

要將總體設計的數據流圖轉化為可以編寫代碼的程序流程圖,其前提是將歷法中所有具體算法用現代數學公式表達出來。然而傳統歷法術文敘述極其簡潔,歷法制定時往往省略了或隱含了某些分支選擇的條件、結果單位的換算和日常使用的簡單算法等。歷法的使用者是人,這些問題在用筆算或是籌算等人工操作時,是很容易被發現并處理的。但我們讓機器代替人進行推算,如果直接根據術文去編寫代碼,不僅不能做到正確的模擬,甚至不能得到可執行的程序。我們必須根據上下文等技術手段補齊或明確這些條件,計算機才能識別。

例如,根據古人的時間概念,所有關于日期計算的結果整數部分大于60時,為了使結果能在一個干支序列內就要在已經算得的結果上減去60;在日食的計算中,如果計算日食初虧時間在日落以后或是復原時間在日出以前,即使有日食我們也不能看見的,這是前面所得的日食食甚和食分就都不能作為結果給出了,而是給出沒有日食的結論。但關于上面的情況,大部分的歷法術文都沒有給出相應說明,因為這些對于歷法使用者的人來說是非常直觀的。

由于隋代以后的歷法使用了更加龐大的上元積年數,在用計算機模擬的過程中,如果處理不當,就會產生很大的誤差。例如,同一個算法,在不同歷法中,其運算順序可能不同,可能是先乘再除,也可能是先除再乘;還有些歷法對計算結果小數部分取整,而有些則四舍五入。這些微小的不同處理方式,可能會被天文常數放大,造成模擬的誤差增大。因此,代碼編寫中涉及到的各種運算和對計算結果的處理時,我們完全依照當時使用歷法進行實際推算的習慣操作,使之與用籌算或筆算得到的結果相一致。我們擬采用Visual Basic 9.0作為古代歷法算法計算機模擬的開發工具,編制出可視化的應用程序。

3.3 軟件的生成與檢測

雖然VB9編輯器和編譯器的調試和編譯功能可以提示我們某些程序編寫上的錯誤,但運行中發生的錯誤是需要合理設計測試案例進行檢測的。但問題是,古代歷法家所提供的使用某部歷法推算的全過程已經完全失傳了,使用這些現成的結果作為程序檢測時不現實的。那么我們將視線轉向現存歷史的有關使用歷法進行推算的結果記錄上面。

古代文獻中有利用某些天象測驗歷法優劣的記載。這些記錄就是當時人們使用某種歷法進行實際推算的結果,我們正確復原的歷法也一定能得到這樣的結果。我們找到這些記錄,并進行整理,確定這些記錄是在什么時間使用什么歷法推算什么天象,然后使用已經編好的某部歷法的程序計算特定時刻的相應天象。當程序計算的結果與史載記錄的結果相同時,就能說明我們對歷法的解釋和所編寫的程序是正確的。當程序計算值與史載記錄不相符時,我們要檢查前面的工作是哪一個環節出了問題。如果僅是程序錯誤,我們要修改程序代碼,重新調試和編譯;如果是術文或常數解讀錯誤,則要重復整個第整體設計和詳細設計的過程,直到準確無誤。

4 結語

過去,中國古代歷法的主要研究方法是文獻考證、算法解讀以及對比評價。而隨著原始資料使用上的限制,更需要研究方法上的突破。我們試圖使用計算機為工具對古代歷法進行研究,使對古代算法的研究方式從文獻到文獻的研究拓展到多學科多工具綜合研究。我們根據古代歷法的特點,闡明傳統歷法計算機模擬的必要性和可行性,給出模擬的總體思路和具體實施方案以及在軟件編寫中注意的問題。我們將能更深入的理解“歷法”這一中華民族特色的傳統文化,更好的發揮歷法在現代科學中的作用。對歷法中算法的計算機模擬和復原研究額能會成為未來天文學史研究的趨勢和熱點問題。

猜你喜歡
枚舉歷法常數
從走馬樓西漢簡歧異干支談漢初歷法混用問題
基于理解性教學的信息技術教學案例研究
關于Landau常數和Euler-Mascheroni常數的漸近展開式以及Stirling級數的系數
發明新歷法
數組在處理枚舉無規律數據中的應用
歷史上最長的一年
萬有引力常數的測量
基于太陽影子定位枚舉法模型的研究
基于枚舉的并行排序與選擇算法設計
紫外分光光度法測定曲札芪苷的解離常數
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合