概述:
·开始日始为:1年1月1日,对应公历622年7月16日。
·在回历中1个闰周为30年,其中平年354天每年,闰年355天,1闰周之中有11个闰年,置闰周期为30年。
·闰年的分布:1闰周中的第2、5、7、10、13、16、18、21、24、26、29年。
·每年12个月,单数月30天,双数月29天,如果是闰年第12月也是30天。
·可见:1闰周有12*29.5*30+11=10631天
为了表述方便,我们临时定义了几个概念:
·INT(a)函数反回小于等于a的最小整数。
·总积日 n:从公元622年7月16日起连续按日计数。积日从0开始,622年7年26的积日为10。
若d0是J2000.0起算的儒略日数,那么 n = d0 + 503105
·周内积日A:某日相对于周首的偏移日数。
·年内积日B:某日相对于年首的偏移日数。
·月内积日d:某日相对于月首的偏移日数。
·周序数k,某一周的周首相对于回历开始日偏移的周数
·年序数y,某一年的年首相对于该年所在周的周首编移的年数
·月序数m,某一月的月首相对于该月所在年的年首编移的月数
·日序数d,某一日相对于该日所在月的月首编移的日数,它相当于月内积日。
由J2000.0起算的儒略日d0求,求回历
n = d0+503105
k = INT( n/10631 )
A = n -k*10631
y = INT( (A+0.5)/354.366 )
B = A - INT( y*354.366+0.5 )
m = INT( (B+0.11)/29.51 )
d = B - INT(29.5*m+0.5)
最后,年记做 y+1+k*30,月记做 m+1,日记做 d+1
已知周序数n、年序数y、月序数m、日序数d,求总积日k
k = 10631*n + INT(y*354.366+0.5) + INT(29.5*m+0.5) + d
已上算法的推导
一、已知总积日n,求周序数k及周内积日A
周序数:k = INT( (n+0.01)/10631 ) ……(式1)
周内积日:A = n -k*10631 ……(式2)
上式中多了个0.01是为了防止整数运算时出错,这里称之为截断补偿。因为计算机做除法时,即使用够整除,它也未必得到整数结果,如0.22/0.22的结果可能是0.99999999999999994,取整计算后得0,而正确值应是1。一些特殊小数,如0.5、0.25、0.125等2的整数次方组合的数可以被计算机精确表示,不会发生截断,所以这里可以不加0.01,即k = INT( n/10631 )。
二、已知周内积日A,求年序数y及年内积日B
(1)先求年序数
平均每年354.366日,所以 c = D/354.366,考虑到序数为整数,则 y = INT(c),然而这种算法在年末或年首可能置闰问题造成y误差1,我们列表如下:
年序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
从列表中发现,正常情况下,c的整数部分应从0开始顺序增加到29。而计算的结果却不是。从表中看出,只要将n的值加一点点,就可以使c的值正常。算式可改写为:
c = (A+0.5)/354.366,即:
y = INT(c) = INT((A+0.5)/354.366) ……(式3)
上式比原来的值多了一个0.5,我们不能增加太多,否则年首正常了,年末却发生错误。把上表中的积日全部减1后重新计算可得年末的年序数,并检查是否正确(正确值应为-1到28)。笔者用Excel软件调试,确定取值0.5是可靠的。
(2)接下来求年内积日B
每年至少有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
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
所以有 e = INT(c) = INT(0.366*y+0.5),式中y指偏移周首的年数(相当于年序数)
因此:B = A - y*354 - e = A - INT(y*354.366+0.5) ……(式4)
(3)判断y年是否为闰年
如果该年的置闰积累数的拟合值满足 d-INT(d) > 0.634 则是闰年(从上表中d的变化规律得到)。
三、已知年内的积日B,求月序数m及月内积日d
(1)求月序数m
如果一年只有354天,算法很简单: c = B/29.5,然后计算 m = INT(c),而事实上,一年可能是354天也可能是355天。当为355天时,使用上式最后一天将会计算为第13个月(月序数为12),如下表所示(闰年):
月序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(此处出错)
解决方法:
对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
c = (B+e)/29.5
= (B(1-a) + a*325)/29.5
≈(B+a*325) / (29.5+29.5*a)
如果用a代a*29.5,那么
c ≈(B+11*a) / (29.5+a),式中0<11*a<0.5
当取a=0.01时,11*a=0.11<0.5
m = INT(c) = INT((B+0.11)/29.51) ……(式5)
(2)求月内积日d
因为m月占用了 INT(29.5*m+0.5),所以
d = B - INT(29.5*m+0.5) ……(式6)
四、综合,已知总积日n,求周序数k、年序数y、月序数m、日序数d(即:月内积日)
按 (式1)到(式6)连续读算
k = INT( n/10631 )
A = n -k*10631
y = INT( (A+0.5)/354.366 )
B = A - INT( y*354.366+0.5 )
m = INT( (B+0.11)/29.51 )
d = B - INT(29.5*m+0.5)
最后:
年记做 y+1+k*30
月记做 m+1
日记做 d+1
五、综合,已知周序数n、年序数y、月序数m、日序数d,求总积日k
k = 10631*n + INT(y*354.366+0.5) + INT(29.5*m+0.5) + d