中 國 古 代 曆 法 的 上 元 積 年 系 統

初稿: 2019年7月


自漢《三統曆》以來至元《授時曆》前,中國曆法都是圍繞上元積年編排的。翻開史書,敘述曆法的第一句都是「上元某某以來,到某某年某某,積某某年」。陳遵媯在《中國天文學史》說:「一部中國曆法史,幾乎可以說是上元的演算史」。可見要深入了解中國古代曆法,不可不識上元積年。本文根據數學家曲安京的《中国历法与数学》[1]和《中国数理天文学》[2]兩書資料,簡單敘述上元積年的起源,計算方法,如何用上元積年調整曆法的天文常數,以及廢除上元積年的原因。


內 容

  1. 引 言
  2. 上 元 積 年 的 推 算
    1. 概 述
    2. 同 餘 方 程 組
    3. 同 餘 方 程 組 有 解 的 充 要 條 件
    4. 演 紀 術
  3. 調 整 天 文 常 數
  4. 上 元 積 年 的 廢 除
   參 考 文 獻

引 言

從唐朝《大衍曆》開始,曆法的結構分成七個部分:氣朔、發斂、日躔、晷漏、月離、交食、五星。氣朔章討論太陽和月亮的平均運動,發斂章討論易卦、氣候和置閏法,日躔章討論太陽運動的不均勻及相關問題,晷漏章討論晷影和漏刻的計算(即正午時晷影長度、太陽出沒時刻、昏旦中星等),月離章討論月亮運動的不均勻及相關問題,交食章討論日食和月食的計算,五星章討論水、金、火、木、土五行星的運行及算法。也就是說中國曆法的內容很接近現代天文年曆的內容。

中國古代的曆法計算,往往是先訂立一個起算點,稱為曆元。基本假設是天象是循環的,曆元定於循環大週朔的起始時刻。初時曆法的曆元是假設其時是甲子日夜半(午夜零時),又是冬至和合朔時刻,稱為朔旦冬至,這特殊時刻往往是推算出來的,而不是考察古天象的記錄所得。到了西漢末年,劉歆用易經穿鑿附會解釋當時《太初曆》的基本天文數據,使曆法帶有神秘色彩。他還提出「太極上元」這概念,不但要求甲子日朔旦冬至,而且還加了若干條件:歲的干支是甲子,又是交食週期的起點,木、火、土、金、水五行星同時會聚冬至點。劉歆將《太初曆》更名為《三統曆》,取太極上元到太初元年(公元前104年)為143127年。

現在我們說的天文學和占星術,古代無論在中國和西方都是不分開的,所以曆法中常有占卜的內容,但是中國曆法也和政治有密切關係。古代的天命論政治思想是君權天授,歷朝都十分重視曆法的制定和頒佈,為了顯示君主掌握天命,曆法合天是十分重要的,這就是中國曆法更改頻繁的主要原因。劉歆故弄玄虛,使曆法變得神秘,其中一個原因是為王莽篡漢提供天命論的理據。可是以後的曆法家制定曆法時,一律效法劉歆的做法推算上元,而且追求上元的理想條件不斷提高。

後來的天文學家發現月亮在天空運行速度不均勻,稱為月行遲疾,月行遲疾的週期就是現在所說的近點月。也發現月球通過黃道與白道的升交點又有不同的週期,即現代所說的交點月。月行遲疾和月亮過黃白交點的時刻對準確預測日食和月食都很重要,於是上元又加了近點月和交點月的週期,要求其時月行最速(或最慢),也就是月球過近(或遠)地點的時刻,亦要求其時月亮過黃白的升(或降)交點。歲差的發現使恆星年這週期也加入上元的條件,上元要求冬至點正好位於北方之中虛宿之內。後來雖然又發現太陽運動不均勻(日行盈縮),但是歷代都假設太陽在冬至運行最快,即假設近點年和回歸年一致而且地球在冬至過近日點,這其實與事實不相符,但是古代的觀測精度不足以察覺假設有誤,因此日行盈縮沒有影響上元的計算。所以理想的上元條件是某甲子年甲子日朔旦冬至,月球過近(遠)地點與升(降)交點,木、火、土、金、水五行星同時會聚冬至點,而冬至點正好位於北方之中虛宿之內。

這樣奇異的天象十分罕見,可以說是不存在的。曆法家根據實測,定出了一組天文常數及日月五星的位置,用這些數據原則上可以推算上元。按照最理想的情形,推算上元涉及的天文常數有回歸年、朔望月、恆星年、交點月、近點月、木、火、土、金、水五行星的會合週期,加上歲名和日名的干支週期,可以列出十一個聯合一次同餘方程組。其實古時也知道五星的運行有遲疾,理論上也要考慮五星過近日點的週期,不過由於古代對五星的近日點週期的觀測數據比較粗糙,就不把這些週期列入同餘方程組。

中國很早已經建立一套解同餘方程組的方法,稱為「大衍總術數」或「孫子定理」或「中國剩餘定理」。這方法曾被學者認為就是古人推算上元積年的方法,但是這說法有兩個嚴重問題。首先,用大衍總術數解這十一個同餘方程組涉及的計算量十分龐大,不要說一千多年前的古代,即使以現代的計算水平,如果沒有計算機的協助也是十分困難的。更重要的是這一方程組未必有解,如果同餘方程組的被除數互質,方程保證有解,但是上元積年的同餘方程組不滿足這條件,因此方程組的餘數必需滿足某些條件才能保證有解,而大衍總術數沒有機制判別方程有解的條件及如何處理無解的情況。還有一事令人費解:上元積年要滿足這十一個同餘方程必定是一個很大的數字,但是考查中國歷代曆法的上元積年數,除了南宋《淳佑曆》和金朝楊級的《大明曆》兩部曆法外,所有曆法的上元積年不超過一億年,此數如果確是解那十一個方程組的話就似嫌太小。那麼曆法家是如何計算上元積年的呢?

可惜的是自元朝《授時曆》廢除上元積年後,推算上元之法湮沒不彰。明代以後,已經沒有人知道傳統曆法的上元究竟是如何推算的。曆法的頒佈是皇權的象征,所以中國古代曆法的制定原理是不公開的秘密,私習曆法歷來被視為違禁的行為。編制曆法全是官辦,曆法的原理只在官方認可的很小範圍內傳播。二十四史中的天文律曆志只是記載曆法的推步方法,算法的構造原理是秘而不宣的。明朝制度規定曆官皆世襲,而明朝《大統曆》沿襲元朝的《授時曆》,基本上無所作為。明成化(1465-1487)以後,日月食往往預報不準,但是世襲曆官不學無術,對傳統曆法的編制機理已經不甚了了,以致朝廷研究改曆時要求助西方傳教士。

自清朝以來,已有學者探求古代曆法的機理,並取得了不少成果,但是古人推算上元積年的方法一直是學界未解之謎,直到最近三十年才被數學家曲安京破解了這個失傳幾百年的算法。根據他的說法,不是每個週期都參與上元積年的推算。絕大多數的上元僅憑歲名、日名、回歸年和朔望月四個週期確定,其他天文常數如近點月、交點月等以觀測數據為參照,然後調整數值來配合算出的上元。上元積年其實隱含著一套制定天文常數的系統,詳情在以下兩節說明。


上 元 積 年 的 推 算概 述

根據曲安京的研究,曆法家推算上元積年的步驟大致如下。首先調取合適的日法,所謂日法是指朔望月或回歸年寫成分數時的分母數字,例如東魏興和曆的朔望月定為6158017/208530日,208530就是興和曆的日法。回歸年和朔望月當然是根據實測,但觀測總會有誤差,在誤差範圍內可以表示成不同的分數,所以可以調取不同的日法。有了回歸年、朔望月和日法後就可以列出三個聯合一次同餘方程組,這樣上元積年的計算只涉及歲名和日名的干支週期、回歸年和朔望月。但是方程未必有解,如果無解或得出的上元積年數超過一億年,就表明這組朔望月和回歸年數據不合用,本輪計算無效,需要重新調取日法,選出另一組在觀測的誤差範圍內可用的回歸年和朔望月數據,再列同餘算式求解,直到求出一個可用的上元積年為止。


同 餘 方 程 組

中國曆法往往以天正冬至作為一歲的起算點,所謂天正是指含冬至的月份,即建子月。由於中國自太初元年(前104年)後大多數以建寅為正月,天正冬至就是指上一年的十一月冬至。若用Ps表示回歸年的日數,PL表示朔望月的日數,N表示某年與上元的積年數,R0表示該年與上一個甲子年的積年數,r1表示該年天正冬至與上一個甲子日夜半的日數,r2表示天正冬至與上一個合朔的日數(即天正冬至的月齡),則可以列出以下的同餘方程組:

N≡R0 (mod 60), PsN≡r1 (mod 60), PsN≡r2 (mod PL)。   (1)

此處≡表示同餘,最左邊的方程是說(N-R0)是60的整數倍,中間的方程是說(PsN-r1)是60的整數倍,最右邊的方程是說(PsN-r2)PL的整數倍。注意R0是整數,但是r1r2一般都不是整數,選取日法的目的是使上述同餘方程組的數字化為整數。

唐朝《麟德曆》以前的中國曆法規定回歸年和朔望月兩者有特定的比例,曆法的閏月因此有特定的週期,稱為閏週。回歸年和朔望月的最小公倍數稱為章,一章所含的回歸年數目稱為章歲,一章所含的朔望月數目稱為章月。例如《三統曆》的章歲是19,章月是235,也就是說一章有19個回歸年,也相當於235個朔望月,因為235=19×12+7,一章有七個閏月,所以《三統曆》的閏月符合十九年七閏法的規律。如果把朔望月的日數寫成PL=U/A,則回歸年的日數是Ps=pU/(qA),此處U、A、p和q都是整數。A就是上面說的日法、p是章月、q是章歲。於是公式(1)可以寫成:

N≡R0 (mod 60), pUN≡R1 (mod 60qA),pN≡R2 (mod q)。   (2)

其中R1=qAr1R2=qr2

如上述,早期曆法取章歲19、章月235,南北朝開始打破傳統。例如北涼《玄始曆》取章歲600、章月7421(600年221閏),北魏《正光曆》取章歲505、章月6246(505年186閏),祖沖之《大明曆》取章歲391、章月4836(391年144閏),隋《開皇曆》取章歲429、章月5306(429年158閏)等。到了唐朝,《麟德曆》及以後的曆法不再預設特定的閏週,回歸年和朔望月都寫成以日法A為分母的分數:Ps=T/APL=U/A,這裡T、U和A都是整數。這樣公式(1)可以寫成:

N≡R0 (mod 60), TN≡R1 (mod 60A),TN≡R2 (mod U)。   (3)

其中R1=Ar1稱為「氣應」,R2=Ar2稱為「閏應」。雖然不再預設閏週,但是閏週還是可以從T/AU/A的最小公倍數求得,只是《麟德曆》及以後的曆法都以定朔註曆,所以閏週不再是閏月的週期。下面會說U、A和T可能要作調整使同餘方程組有解,廢除閏週前,只能調整U和A,廢除閏週後,U、A和T都可自由調整,這就是兩種方法在計算上元時的差異。


同 餘 方 程 組 有 解 的 充 要 條 件

在解這些同餘方程組前,應該先判別方程組是否有解,否則很可能會徒勞無功。這裡用公式(3)的方程組說明。最左邊方程的通解是N=R0+60m,而m是任意整數,把這通解代入中間的方程得

T(R0+60m)=R1+60An,

此處n是整數。這公式可寫成

60g1(mt-na)=R1-TR0,   (4)

這裡g1=gcd(T,A)是T和A的最大公約數,而t=T/g1a=A/g1,所以t和a互質。由於mt-na是整數,方程(4)有解的充要條件是60g1|(R1-TR0), 也就是說R1-TR0必需是60g1的整數倍。這個充要條件只是公式(3)左邊兩個方程有解的條件,並沒有考慮最右邊的方程,所以還有兩個額外的充要條件。將通解N=R0+60m代入公式(3)最右邊的方程,然後重復類似以上的運算可得方程有解的第二個充要條件:g2|(R2-R0T),其中g2=gcd(60T,U)。第三個充要條件可將公式(3)中間方程的通解代入最右邊的方程推導出來,結果是:g3|(R1-R2),而g3=gcd(60A,U)。綜合以上結果,同餘方程組(3)有解的充要條件是:

60g1|(R1-TR0),g2|(R2-R0T)g3|(R1-R2)
g1=gcd(T,A),g2=gcd(60T,U)g3=gcd(60A,U)

如果條件不滿足,就要調節R1=Ar1R2=Ar2的數值,r1r2由觀測而得,所以不能調整太大,一般的原則是r1r2與觀測值的偏差不能超過一刻。清朝以前是把一日分為一百刻,所以一刻是0.01日,即14.4分鐘。如果在正負一刻範圍內沒有合用的R1R2使方程有解,則需要重新選取日法A,T和U也要重新選取使T/A和U/A與實測的回歸年和朔望月的偏差在可接受的誤差範圍內,然後重新布列同餘方程組,再檢查是否能調出合用的R1R2,否則又要重新選取A、T和U重新計算,直至得出合用的R1R2為止。

上述的調整方法只是一個設想,曆法家可能不是這樣調整這些參數的,而是可能用演紀術邊算邊調參數。


演 紀 術

曆家解這些方程組的方法是「演紀術」,此術很簡單,這裡仍以公式(3)的方程組為例說明。演紀術第一步是先解其中一條方程,這裡就選最左邊的方程,上面已求得方程的通解: N=R0+60m。第二步是將通解代入中間的方程,這在上面也已計算了,結果是公式(4),方程有解的充要條件是60g1|(R1-TR0),如果條件不滿足就要調整R1,如果在可接受的範圍內沒有合用的R1,就要重新選取T、U和A。調好了R1後,公式(4)可以改寫成:

mt-na=S1S1=(R1-TR0)/(60g1)
⇒  mt ≡ S1 (mod a)。

欲解此方程,首先是解μt≡1 (mod a),這可用大衍求一術計算,算出μ後乘S1便得m。注意m不是唯一的,將其中一解加上a的整數倍也是一解。用M表示正整數中的最小的一個解,則可將通解寫成m=M+ka,其中k是任意整數,而N0=R0+60M就是上一次冬至發生在甲子年甲子日夜半與欲求之天正冬至的積年數,但是此時並非合朔,所以還得求出整數k使曆元滿足甲子年甲子日夜半朔旦冬至,這就要將通解N=R0+60(M+ka)代入公式(3)最右邊的方程,結果是

TR0+60T(M+ka)=R2+Ub,b是整數,
⇒  60Tak-Ub=R2-TR0-60TM。

方程有解的充要條件是gcd(60Ta,U)|(R2-TR0-60TM),如果條件不滿足,就要調整R2,如果在可接受的範圍內沒有合用的R2,就要重新選取T、U和A再重算。調好參數後可以把方程改寫如下。

g=gcd(60Ta,U)v=60Ta/gu=U/gS3=(R2-TR0-60TM)/g,則得
vk-ub=S3 ⇒ vk≡S3 (mod u)

欲求k,先用大衍求一術解vz≡1 (mod u),然後把算出的z乘S3便得k,但是k不是唯一的,可以加上u的整數倍求出最小的正整數解,稱之為K,那麼上元積年N便是 N=R0+60(M+Ka)。如果求出的積年大於一億年,則本輪計算無效,須要從新選取A、T和U直至得出N小於一億的解為止。

簡言之,演紀術的精義是先解一個方程,把通解代入第二個方程求解,然後再把通解代入第三個方程;而大衍總術數卻是同時處理三個方程,涉及許多大數的連乘連除,計算量十分龐大,不及演紀術邊算邊化簡,計算量比大衍總術數小很多倍。中國曆法在後期所用的T、U和A都是很大的數字,演紀上元的簡捷實用效果是非同小可的,而且演紀術提供了方程有解的條件,在計算時可以按情況調整參數。

求得一個合用的上元積年後,下一步是調整其他天文常數來配合這個上元,這就是下一節要討論的問題。


調 整 天 文 常 數

求出了上元積年後,就要調整其他天文常數配合既定的上元。這是因為上元不單止是朔旦冬至,亦是月球過近(遠)地點、過升(降)交點及五星會聚之時刻,但是相關的週期都沒有參與上元的推算,算出的上元當然不能符合實測數據,所以必需調整這些週期。現在以近點月為例說明如何調整數據。

首先引入兩個函數:floor(x)表示不大於x的最大整數,
mod(X,Y)=X-Y·floor(X/Y)是X除以Y後所得之餘數。

假設某曆法推出某年冬至的上元積年數是一萬年,又假設這部曆法的回歸年取(365+97/400)日=365.2425日。假設觀測得出在冬至時月球過了近地點已有12.3457日,而近點月的實測值是27.5546日。這個上元是否符合觀測數據?上元積年一萬年,就是說這冬至距上元積日3652425日,如果假設月球在上元過近地點,近點月是27.5546日,則這冬至距上一次月球過近地點有mod(3652425,27.5546)日=7.6608日,顯然不符合觀測值。所以必需將近點月的數值改為Pa,使得mod(3652425,Pa)=12.3457,其解是要求3652425-12.3457是Pa的整數倍,由此得出Pa=3652412.6543/n,而n是任何大於0的整數。當然Pa越接近實測數值越好,如果取Pa=27.5546,則n=3652412.6543/27.5546=132551.83顯然不是整數,取最接近的整數132552得Pa=3652412.6543/132552=27.55456465613495,比實測值只是小了三秒。古代的觀測精度沒有這麼高,取這個數值不會損害曆法的精度,只是這個Pa並非簡單分數,計算時不方便,一般會選取另一個Pa既能符合實測數據,又能表示成較為簡單的分數。上元積年的數值越大,就越容易找到適合的分數既能符合觀測數據,又能附會既定的上元。

現代天文學的常數系統可分為定義常數(defining constants),初始常數(primary constants)和推導常數(derived constants)等。顧名思義,定義常數是根據定義而制定的常數,例如光速299792458米/秒就是定義常數,一米的長度就是定義為光在一秒鐘所走距離的299792458分之一。初始常數是由觀測而定的常數,例如地球赤道半徑。推導常數是由初始常數或定義常數推導出的常數,例如太陽與地球的質量比。以現代天文學的觀念來說,用既定上元來定出的天文常數就是推導常數,所以在上元這套曆法系統,恆星年、交點月、近點月、五星會合週期等都是推導常數。這說法看似不妥,因為我們認為這些常數應是靠觀測而定,而不應是推導出來的。但是在上元這套系統中,這些常數的實測值只是參考值,曆法採用的數值是為了附會上元而推出的數值,只是在「推導」過程中不能使數值太偏離實測值,否則曆法不能與天象相符。

雖然古代大部份的曆法都是調整天文常數附會上元,也有人不贊同這做法,例如杜預在其《春秋長曆》說:「《書》所謂『欽若昊天,曆象日月星辰』,《易》所謂『治曆明時』,言當順天以求合,非為合以驗天也。」「順天以求合」,是指用實測數據直接推算天象;「為合以驗天」,指以實測數據為參照,調整選擇與之相近的曆法數據來配合既定的上元。由於日月食的推算要從上元算起,故需要「為合以驗天」。楊偉制《景初曆》(237年),破天荒取交食週期及近點月週期的起點游離於上元之外,從而大幅度提高了近點月的精度。南北朝何承天的《元嘉曆》(443年),將五星會合週期各立「後元」,大大提高了五星會合週期的精度。何承天也贊同治曆應「順天以求合」。但是何承天的做法遭受非議,以後的曆家仍繼續調整天文常數附會上元。

上面的例子說明了如果上元積年足夠大,是可以比較容易找到合用的數值既可附會上元,亦可接近觀測數據。但是上元積年數大使計算不方便,所以必須有所取捨,歷代大多以一億年為上元積年的上限。由於觀測精度的提高,這限制使曆法的精度無法提高,最終導致上元積年的廢除。


上 元 積 年 的 廢 除

上元系統的最大弊病是計算複雜,這系統不但在曆法的制定和計算上無甚幫助,反而阻礙曆法的改良,最終在元朝《授時曆》被廢除。李謙應召作《授時曆議》,說明《授時曆》的進步,同時「考證前代人為附會之失」:

曆法之作,所以步日月之躔離,候氣朔之盈虛,不揆其端,無以測知天道,而與之吻合。然日月之行遲速不同,氣朔之運參差不一,昔人立法,必推求往古生數之始,謂之演紀上元。當斯之際,日月五星同度,如合璧連珠然。惟其世代綿遠,馴積其數至逾億萬,後人厭其布算繁多,互相推考,斷截其數而增損日法,以為得改憲之術,此歷代積年日法所以不能相同者也。然行之未遠,浸複差失,蓋天道自然,豈人為附會所能苟合哉。夫七政運行於天,進退自有常度,苟原始要終,候驗周匝,則象數昭著,有不容隱者,又何必舍目前簡易之法,而求億萬年宏闊之術哉。

   —《元史‧歷志》卷五十三,《歷代天文律曆等志彙編》(九),三三五七頁。

由於觀測精度提高,能選的日法也變得大,同餘方程組解出的積年數達到億萬並不少見。治曆者對於大於億年的積年數在布算或附會的過程中感到不便,要求大於一億的積年不合用,於是多次調整日法,反復推考,「斷截其數」以得出合用的積年。但是過了不久就發現與天象不符(「行之未遠,浸複差失」),於是又要修改曆法重新推算上元積年。兩宋三百多年間用了十九部曆法,平均十七年就要改一次曆法,一方面說明了觀測的進步,曆法的誤差很容易被發現,另一方面說明曆法並沒有大改良,其中原因很可能就是曆法被上元系統束縛著。滑稽的是,這些曆法的開首術文雖然云:「上元至今積若干千萬年」,但是實際上過了二十年左右已發現不合天。元朝的《授時曆》於1281年頒行,用至元朝滅亡,明朝建立後,更名為《大統曆》,用至明末。除了微小修改外,《大統曆》基本上沿襲《授時曆》,所以《授時曆》可以說在中國用了超過360年。《授時曆》之精湛,除了廢上元積年外,還因為當時改良了天文儀器,使測驗精度大為提高,在理論推算上也集歷代諸家之大成。



參 考 文 獻