有了恒星位置的计算方法,就可以反求恒星在某位置时的时间。
star部分即恒星位置计算,参见https://blog.csdn.net/weixin_42763614/article/details/83388789
反求时间即利用插值法逆求。
from star import *
def interpolation(star, angle, n0, t1, t2, t3): # 插座计算恒星在赤经为angle(角秒)时的时间
# 插值表t1:ra1,t2:ra2,t3:ra3(儒略世纪数表示的时间)
appPlace(star, t1)
ra1 = star.ra % 360 * 3600
appPlace(star, t2)
ra2 = star.ra % 360 * 3600
appPlace(star, t3)
ra3 = star.ra % 360 * 3600
a = ra2 - ra1
b = ra3 - ra2
c = ra1 + ra3 - 2*ra2
n = -2*(ra2-angle) / (a + b + c*n0)
return n
def iteration(star, angle, t1, t3): # 迭代修正精度,angle为度数
t2 = (t1+t3) / 2
n0 = 0 # 初值
while True:
n = interpolation(star, angle * 3600, n0, t1, t2, t3)
if n0 == n: break
n0 = n
return t2date(t2+n*(t2-t1))
以下举例史料中典型的天象时间问题,即《尧典》四仲中星和《汉书·律历志》二十八宿位置 。
《尧典》四仲中星时间
i = 1
for star in szzx:
# 所求时间范围
t1 = -30 # 约公元前1000年
t3 = -40 # 约公元前3000年
date = iteration(star, 90*i%360, t1, t3)
JD = ephem.julian_date(date)
t = (JD - 2451545) / 36525
appPlace(star, t)
d = ephem.Date(date)
year = d.tuple() # 获得年份,由于目视误差,具体时刻不具有参考价值
print(star.name, year[0], appPlace(star, t))
i += 1
插值计算的精度不高,寻找好的差值表范围可以提高精度,但也可以使用牛顿迭代法向真实值逼近,获得较高精度。
计算结果:
星宿一 -2155年 (赤经:90.00042309673259)
心宿二 -2931年 (赤经:179.90138264459966)
虚宿一 -1859年 (赤经:270.0102335767864)
昴宿一 -2173年 (赤经:359.99930754645504)
该值对比《中国古代天体测量学及天文仪器》的结果(见19页),发现书中以心宿二赤经为180度时在公元前2125年,与计算值相差甚大,根据其所提供的赤经表(与本程序计算结果误差在0.1°以内),宜在[前2500,前3000]年间,应为排印错误。
由此可见四仲中星的最大差值可达1000年,其实心宿二与星宿一的J2000.0赤道坐标相差达7h(15°),根据岁差约70年差一度,宜有此误。
《汉书》二十八宿时间
《律历志》给出的二十四节气的入宿度,只有冬至点是实测得到的,其他是根据简单内插法求算的。因此计算《汉志》所载的二十八宿位置测定的时间,也只需计算冬至点在牛初度时的时间。
此时即是求牛宿距星在赤经为270度的时间。估值在殷周到公元元年(约《汉书》成书时间)仅需使用iteration()函数。
print(iteration(niu, 270,-20,-30))
求得结果约在公元前451年左右,此时牛宿距星的赤经为270.00度。考虑到测量误差,可能更晚。
另可利用ephem模块求算冬至与天正朔在同一天的时间(参见:https://blog.csdn.net/weixin_42763614/article/details/83189459),即公元前427年。二者时间相近,可见当时的确为创制历法做过实际观测。