摘? 要: 基于農(nóng)歷節(jié)氣的內(nèi)在規(guī)律提出了一種新型實用列表算法——按位列表法(BSMA),利用單片機Tm8706實現(xiàn)了電子萬年歷的研究和開發(fā)。
關(guān)鍵詞: 節(jié)氣? 列表法? 微處理器? 單片機? 算法
?
農(nóng)歷24節(jié)氣是我國民間傳統(tǒng)節(jié)令,對于農(nóng)事活動有廣泛的應(yīng)用價值。因而帶有24節(jié)氣的電子萬年歷在農(nóng)村有廣泛的市場。
本文通過分析24節(jié)氣,找出了其中內(nèi)在的隱含規(guī)律,并且根據(jù)這種規(guī)律提出了一種最新的查表方法。由于這種查表方法是基于位查詢的,所以稱之為按位列表法(Bit Schedule Method Arithmetic,BSMA)。
1? 陰歷節(jié)氣的隱含規(guī)律
為了便于考察50年中無規(guī)律的陰歷節(jié)氣分布時間,本文利用C語言在計算機中實現(xiàn)了50年(2000~2049年)的陽歷和陰歷節(jié)氣分布時間表。由于數(shù)據(jù)龐大,所以僅列出其中部分陽歷年對應(yīng)的前6個節(jié)氣日期,見表1。
?
表1中,每年的節(jié)氣具體日期雖然都在一定的范圍內(nèi)變動,但是變動的趨勢毫無規(guī)律可尋,每個月的具體節(jié)氣日期有時候推前一、二天,有時候推后一、二天。但是,從這張復(fù)雜表格中的眾多數(shù)據(jù)中可以發(fā)現(xiàn)一個規(guī)律:雖然,無法獲得這些節(jié)氣變化的具體日期,但是,這些日期的變化總是在3天之內(nèi)發(fā)生。例如:每年的第1個節(jié)氣(小寒)出現(xiàn)在1月的5日、6日2天中的某一天;每年的第2個節(jié)氣(大寒)出現(xiàn)在1月的19日、20日、21日3天中的某一天。這樣,只要固定每個節(jié)氣的基本日期,然后專門針對這二、三天編制一個相對日期的表格就可以了。考慮到最多變化范圍是3天,所以這個相對日期可以取值為1、0和-1。
選定的基本日期是:1月到3月的節(jié)氣基本日期:6/20、4/19、6/21;4月到6月的節(jié)氣基本日期:5/20、6/21、6/21;6月到9月的節(jié)氣基本日期:7/23、8/23、8/23;10月到12月的節(jié)氣基本日期:8/24、8/22、7/22。
根據(jù)以上的思路,可得到表2所示的相對值表。
仔細(xì)觀察表2,可以得到以下關(guān)于節(jié)氣日期相對值的規(guī)律性結(jié)論:
(1)只有4個節(jié)氣(大寒、夏至、寒露、小雪)是3個相對值(1,-1和0)同時出現(xiàn)。
(2)其他的20個節(jié)氣中僅僅出現(xiàn)了0和-1這2個相對值。
(3)在有3個相對值的4個節(jié)氣(大寒、夏至、寒露、小雪)中,2044年以前,出現(xiàn)的非零相對值都是1;而2044年以及2044年以后,出現(xiàn)的非零相對值都是-1;
?
也就是說在50年內(nèi),大寒(2)、夏至(12)、寒露(19)和小雪(22)這4個節(jié)氣日期變化相對較多,一共有3天,它們的日期相對值可能需要使用3個狀態(tài)值來表示。
圖1是以上4條農(nóng)歷節(jié)氣日期規(guī)律的相對值分布簡圖。
?
根據(jù)表2和圖1所示的農(nóng)歷節(jié)氣日期排布規(guī)律和形式,就可以構(gòu)造一個表格,并且結(jié)合相應(yīng)的算法來計算某個陽歷日期所對應(yīng)的陰歷節(jié)氣了。
2?按位列表法(BSMA)及其編碼方法
利用上節(jié)分析結(jié)果,設(shè)想使用最少的字節(jié)來編制1個表格,使其包含了50年內(nèi)的所有相對值分布信息。由于1年包含農(nóng)歷的24個節(jié)氣,也就是說共有24個日期相對值狀態(tài)量。
為了能夠盡量減少存儲空間,可以使用1個位來代表1個農(nóng)歷的節(jié)氣日期相對值。這樣一年的24個節(jié)氣就可以用24個位來表示,也就是3個字節(jié)(每個字節(jié)8個位)表示。這就是所說的按位列表法。
由于農(nóng)歷節(jié)氣日期相對值最多有3種狀態(tài):-1、0和1,而1個位僅僅有2種狀態(tài):0和1。為了能夠把3種狀態(tài)融合進(jìn)2種狀態(tài)中,本文根據(jù)上節(jié)中節(jié)氣日期相對值的規(guī)律性結(jié)論,采取了具有條件的二值狀態(tài)來表示三值狀態(tài),制定了如表3所示的編碼規(guī)則。
?
利用以上的規(guī)則就可對50年的24個節(jié)氣進(jìn)行編碼,得到如表4所示的編碼表。
?
由此看出,使用這種按位編碼的方式對農(nóng)歷日期相對值進(jìn)行編碼時,一年24個節(jié)氣的日期只需要3個字節(jié)就可以明確表示了。50年的節(jié)氣表,只需要150個字節(jié)的存儲空間。年份越多,這種編碼發(fā)方式能夠節(jié)約的存儲空間越大,優(yōu)勢越明顯。
3?BSMA法在單片機中的實現(xiàn)
本文使用的單片機是十速公司的4位機,型號為Tm8706。這種單片機的結(jié)構(gòu)與8位機類似,但是功能遠(yuǎn)遜于8位計算機。選此機型的原因是它具有結(jié)構(gòu)簡單、成本低的優(yōu)勢,同時還包括了普通單片機的基本功能。它包含了256個字節(jié)的RAM、2KB的ROM、定時器、外部中斷、內(nèi)部中斷,此外,還有省電功能和驅(qū)動LED的功能。
由于其他的功能程序已經(jīng)占用了較大的存儲空間。所以能夠用于農(nóng)歷節(jié)氣查詢的程序的空間不大,僅僅有0.5KB的容量。也就是說表格和查表程序一共只有0.5KB的空間。表格占用的空間越大,可寫程序的空間就越小。
如果使用表1所示的50年農(nóng)歷24節(jié)氣日期表,僅僅表格就需要使用50×24個字節(jié)=1200個字節(jié)的存儲空間,其要求空間遠(yuǎn)遠(yuǎn)超出了0.5KB的容量。而使用LBA編碼方法得到的表格,只需要150個字節(jié),存儲空間僅僅是表1所需存儲空間的1/8,其余部分可以供查表程序使用。
在單片機中,查表程序是使用匯編程序完成的,實現(xiàn)起來也很容易。為了便于理解,這里把查表程序用C語言實現(xiàn)的部分介紹如下:
輸入?yún)?shù)是陽歷的年月日:day、month、year,要求查表尋找它附近的農(nóng)歷節(jié)氣和農(nóng)歷節(jié)氣的日期。
if(day>=15) half_mon=1; //判斷是否是上半月
else half_mon=0;
col=(month-1)*2+half_mon; //獲得節(jié)氣順序標(biāo)號(0~23)
kc_byte=col/8; //獲得節(jié)氣日期的相對值所在的
//字節(jié)位置(0~2)
kc_bit=col%8; //獲得節(jié)氣日期的相對值在字節(jié)中的
//位位置(0~7)
tmp_modi=modi_datas[year-2000][kc_byte];
//獲得節(jié)氣日期相對值所在字節(jié)
value=( (tmp_modi< //日期相對值狀態(tài) if(value!=0){ //判斷年份,以決定節(jié)氣相對值1代表1 //還是-1。 if( (col==1 || col==11 || col==18 || col==21) && year<2044) ????????????? J_qi=days[col]+1; //年份<2044的4個特定 //月份中,取+1。 else ????????????? J_qi=days[col]-1; //其他情況下,取-1。 } else J_qi=days[col]; //狀態(tài)為0,節(jié)氣日期相對值 //為節(jié)氣基本日期值。 由此程序即可獲得所輸入陽歷日期(年、月、日)附近的農(nóng)歷節(jié)氣準(zhǔn)確日期值。 通過上面的BSMA列表編碼和查詢的方法,實現(xiàn)了基于四位單片機的萬年歷的研制和實現(xiàn)。它用匯編程序方便地實現(xiàn)了陰歷24節(jié)氣功能,同時還可以方便地算出某年的某天距離下一個節(jié)氣的天數(shù)。 從上面可以看出,按位列表法(BSMA)思路清晰明了,實現(xiàn)起來非常方便,同時節(jié)省了大量的ROM空間。所做萬年歷的時間跨度越大,LBA算法在節(jié)省ROM空間的優(yōu)勢就越明顯。 ? 參考文獻(xiàn) 1? 李勇,許邦信.太陽黃經(jīng)和節(jié)氣時間的近似推算與Newcomb太陽表.南京大學(xué)學(xué)報,1995;31(3) 2? 張培瑜,黃洪峰.中歷及二十四節(jié)氣時刻計算.廣西科學(xué),1994;1(3)