?? sm3.htm
字號:
<html><head><title>幫助</title></head>
<body>
<center>
<table width=780 border=0 cellpadding=3 cellspacing=0>
<tr><td style='line-height:150%;font-size:16px;text-indent: 20'>
<p><a href="readme.htm">返回</a></p>
<p align=center><b>第三章 回歷計算</b></p>
<p><b>概述:</b><br><br>
·開始日始為:1年1月1日,對應公歷622年7月16日。<br>
·在回歷中1個閏周為30年,其中平年354天每年,閏年355天,1閏周之中有11個閏年,置閏周期為30年。<br>
·閏年的分布:1閏周中的第2、5、7、10、13、16、18、21、24、26、29年。<br>
·每年12個月,單數月30天,雙數月29天,如果是閏年第12月也是30天。<br>
·可見:1閏周有12*29.5*30+11=10631天
</p>
<p><b>為了表述方便,我們臨時定義了幾個概念:</b><br><br>
·INT(a)函數反回小于等于a的最小整數。<br>
·總積日 n:從公元622年7月16日起連續按日計數。積日從0開始,622年7年26的積日為10。<br>
若d0是J2000.0起算的儒略日數,那么 n = d0 + 503105<br>
·周內積日A:某日相對于周首的偏移日數。<br>
·年內積日B:某日相對于年首的偏移日數。<br>
·月內積日d:某日相對于月首的偏移日數。<br><br>
·周序數k,某一周的周首相對于回歷開始日偏移的周數<br>
·年序數y,某一年的年首相對于該年所在周的周首編移的年數<br>
·月序數m,某一月的月首相對于該月所在年的年首編移的月數<br>
·日序數d,某一日相對于該日所在月的月首編移的日數,它相當于月內積日。 <br>
</p>
<p><b>由J2000.0起算的儒略日d0求,求回歷</b></p>
<p>n = d0+503105</p>
<p>k = INT( (n+0.1)/10631 )</p>
<p>A = n -k*10631</p>
<p>y = INT( (A+0.5)/354.366 )</p>
<p>B = A - INT( y*354.366+0.5 )</p>
<p>m = INT( (B+0.11)/29.51 )</p>
<p>d = B - INT(29.5001*m+0.5)</p>
<p>最后,年記做 y+1+k*30,月記做 m+1,日記做 d+1</p>
<p><b>已知周序數n、年序數y、月序數m、日序數d,求總積日k</b></p>
<p>k = 10631*n + INT(y*354.366+0.5) + INT(29.5001*m+0.5) + d</p>
<hr>
<p><b>已上算法的推導</b></p>
<p><b>一、已知總積日n,求周序數k及周內積日A</b></p>
<p>周序數:k = INT( (n+0.01)/10631 ) ……(式1)</p>
<p>周內積日:A = n -k*10631 ……(式2)</p>
<p>上式中多了個0.01是為了防止整數運算時出錯,這里稱之為截斷補償。因為計算機做除法時,即使用夠整除,它也未必得到整數結果,如0.22/0.22的結果可能是0.99999999999999994,取整計算后得0,而正確值應是1。一些特殊小數,如0.5、0.25、0.125等2的整數次方組合的數可能被計算機精確表示,不會發生截斷。</p>
<p><b>二、已知周內積日A,求年序數y及年內積日B</b><br><br>
<b>(1)先求年序數</b><br><br>
平均每年354.366日,所以 c = D/354.366,考慮到序數為整數,則 y = INT(c),然而這種算法在年末或年首可能置閏問題造成y誤差1,我們列表如下:
</p>
<pre>
年序y 積日A c
0年首 0 0
1年首 354 0.99896717
2年首 709 2.00075628
3年首 1063 2.99972345
4年首 1417 3.998690619
5年首 1772 5.00047973
6年首 2126 5.9994469
7年首 2481 7.00123601
8年首 2835 8.00020318
9年首 3189 8.999170349
10年首 3544 10.00095946
11年首 3898 10.99992663
12年首 4252 11.9988938
13年首 4607 13.00068291
14年首 4961 13.99965008
15年首 5315 14.99861725
16年首 5670 16.00040636
17年首 6024 16.99937353
18年首 6379 18.00116264
19年首 6733 19.00012981
20年首 7087 19.99909698
21年首 7442 21.00088609
22年首 7796 21.99985326
23年首 8150 22.99882043
24年首 8505 24.00060954
25年首 8859 24.99957671
26年首 9214 26.00136582
27年首 9568 27.00033299
28年首 9922 27.99930016
29年首 10277 29.00108927
</pre>
<p>從列表中發現,正常情況下,c的整數部分應從0開始順序增加到29。而計算的結果卻不是。從表中看出,只要將n的值加一點點,就可以使c的值正常。算式可改寫為:</p>
<p> c = (A+0.5)/354.366,即:</p>
<p> y = INT(c) = INT((A+0.5)/354.366) ……(式3)</p>
<p>上式比原來的值多了一個0.5,我們不能增加太多,否則年首正常了,年末卻發生錯誤。把上表中的積日全部減1后重新計算可得年末的年序數,并檢查是否正確(正確值應為-1到28)。筆者用Excel軟件調試,確定取值0.5是可靠的。</p>
<p><b>(2)接下來求年內積日B</b></p>
<p>每年至少有354天,所以年內積日大約為 B = A - y*354,然而這種算法沒有考慮因閏年對積日的影響。在回歷中,30年置11閏,平均每年354.366日。小數0.366正是"閏的速度",即每年閏了0.366日。這樣,y年后閏了c = 0.366*y日,我們對f取整得到置閏日數。不過,如此計算的結果與歷法中規定的閏年不會發生在相同的年份。可以使用Excel計算并比對,不難發現,只要加上0.5日就可解決問題。下表中e是按照歷法規定的的閏年進行積累的置閏日數,置閏積數的擬合算式改寫為 c = 0.366*y + 0.5,從下表中看出這樣c的整數部分與就是e</p>
<pre>
y年序 e積數 c(擬合)
0 0 0.5
1(閏) 0 0.866
2 1 1.232
3 1 1.598
4(閏) 1 1.964
5 2 2.33
6(閏) 2 2.696
7 3 3.062
8 3 3.428
9(閏) 3 3.794
10 4 4.16
11 4 4.526
12(閏) 4 4.892
13 5 5.258
14 5 5.624
15(閏) 5 5.99
16 6 6.356
17(閏) 6 6.722
18 7 7.088
19 7 7.454
20(閏) 7 7.82
21 8 8.186
22 8 8.552
23(閏) 8 8.918
24 9 9.284
25(閏) 9 9.65
26 10 10.016
27 10 10.382
28(閏) 10 10.748
29 11 11.114
30 11 11.48
</pre>
<p>所以有 e = INT(c) = INT(0.366*y+0.5),式中y指偏移周首的年數(相當于年序數)</p>
<p>因此:B = A - y*354 - e = A - INT(y*354.366+0.5) ……(式4)</p>
<p><b>(3)判斷y年是否為閏年</b></p>
<p>如果該年的置閏積累數的擬合值滿足 d-INT(d) > 0.634 則是閏年(從上表中d的變化規律得到)。</p>
<p><b>三、已知年內的積日B,求月序數m及月內積日d</b></p>
<p>(1)求月序數m</p>
<p>如果一年只有354天,算法很簡單: c = B/29.5,然后計算 m = INT(c),而事實上,一年可能是354天也可能是355天。當為355天時,使用上式最后一天將會計算為第13個月(月序數為12),如下表所示(閏年):</p>
<pre>
月序m 積日B c=B/29.5
0月首 0 0
1月首 30 1.016949153
2月首 59 2
3月首 89 3.016949153
4月首 118 4
5月首 148 5.016949153
6月首 177 6
7月首 207 7.016949153
8月首 236 8
9月首 266 9.016949153
10月首 295 10
11月首 325 11.01694915
11月末 354 12(此處出錯)
</pre>
<p>解決方法:</p>
<p>對B做一個線性補償,補償值為小量e。當B<325(m<11)時,e>0,當B>325時e<0。通過這種補償,當m<11時c時增加了一點,反之c減小了一點,這樣,表中最后一行c的整數部分減小1,其它各行c的整數部分保持不變,c的值全部正確了。我們還應注意,不管m取0到12的任何值時,e的值不能超0.5。比如首月的月末,c = B/29.5 = 29/29.5=0.983,這是正確的,如果B補償了0.5,那么 c = 29.5/29.5 =1(變成第2月,顯然確誤)。我們設e = a*(325-B),a是我們選取的一個正常數,同時因e<0.5,所以a*(325-0)<0.5,得325*a<0.5</p>
<p>c = (B+e)/29.5<br>
= (B(1-a) + a*325)/29.5<br>
≈(B+a*325) / (29.5+29.5*a)<br>
如果用a代a*29.5,那么<br>
c ≈(B+11*a) / (29.5+a),式中0<11*a<0.5<br><br>
當取a=0.01時,11*a=0.11<0.5<br>
m = INT(c) = INT((B+0.11)/29.51) ……(式5)<br>
</p>
<p>(2)求月內積日d</p>
<p>因為m月占用了 INT(29.5*m+0.5),所以</p>
<p>d = B - INT(29.5001*m+0.5) ……(式6)</p>
<p>式中式中29.5后面多了0.0001,用于截斷補償。</p>
<p><b>四、綜合,已知總積日n,求周序數k、年序數y、月序數m、日序數d(即:月內積日)</b></p>
<p>按 (式1)到(式6)連續讀算</p>
<p>k = INT( (n+0.1)/10631 )</p>
<p>A = n -k*10631</p>
<p>y = INT( (A+0.5)/354.366 )</p>
<p>B = A - INT( y*354.366+0.5 )</p>
<p>m = INT( (B+0.11)/29.51 )</p>
<p>d = B - INT(29.5001*m+0.5)</p>
<p>最后:</p>
<p>年記做 y+1+k*30</p>
<p>月記做 m+1</p>
<p>日記做 d+1</p>
<p><b>五、綜合,已知周序數n、年序數y、月序數m、日序數d,求總積日k</b></p>
<p>k = 10631*n + INT(y*354.366+0.5) + INT(29.5001*m+0.5) + d</p>
</td></tr>
</table>
</center>
</body></html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -