中國農歷二百年算法及年歷 - 和榮筆記 - v4.16,楊和榮
太阳的位置和经度
本節介紹了計算太陽位置的公式和Keith的QBasic程式,修改後可以在QB64上運行。 該程式可以計算驗證二分點和二至點的日期和時間,在1950年至2050年之間的誤差為0.01度。
前面我講到沒有簡單的計算方法二分點和二至點。 但後來我發現了 Keith Burnett 編寫的 QBasic 簡單程式,發表於 "太陽的位置"( http://www.stargazing.net/kepler/sun.html)。
Keith的程序採用了《1996年天文年鑒》書中的 計算太陽的經度和位置的公式, 精度在1950年至2050年之間的0.01度。
下面是Keith的程式的原始程式碼:
'*********************************************************
' This program will calculate the position of the Sun
' using a low precision method found on page C24 of the
' 1996 Astronomical Almanac.
'
' The method is good to 0.01 degrees in the sky over the
' period 1950 to 2050.
'
' QBASIC program by Keith Burnett (kburnett@geocity.com)
'
'
' Work in double precision and define some constants
'
DEFDBL A-Z
pr1$ = "\ \#####.##"
pr2$ = "\ \#####.#####"
pr3$ = "\ \#####.###"
pi = 4 * ATN(1)
tpi = 2 * pi
twopi = tpi
degs = 180 / pi
rads = pi / 180
'
' Get the days to J2000
' h is UT in decimal hours
' FNday only works between 1901 to 2099 - see Meeus chapter 7
'
DEF FNday (y, m, d, h) = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 _
+ 275 * m \ 9 + d - 730531.5 + h / 24
'
' define some arc cos and arc sin functions and a modified inverse
' tangent function
'
DEF FNacos (x)
s = SQR(1 - x * x)
FNacos = ATN(s / x)
END DEF
DEF FNasin (x)
c = SQR(1 - x * x)
FNasin = ATN(x / c)
END DEF
'
' the atn2 function below returns an angle in the range 0 to two pi
' depending on the signs of x and y.
'
DEF FNatn2 (y, x)
a = ATN(y / x)
IF x < 0 THEN a = a + pi
IF (y < 0) AND (x > 0) THEN a = a + tpi
FNatn2 = a
END DEF
'
' the function below returns the true integer part,
' even for negative numbers
'
DEF FNipart (x) = SGN(x) * INT(ABS(x))
'
' the function below returns an angle in the range
' 0 to two pi
'
DEF FNrange (x)
b = x / tpi
a = tpi * (b - FNipart(b))
IF a < 0 THEN a = tpi + a
FNrange = a
END DEF
'
' Find the ecliptic longitude of the Sun
'
DEF FNsun (d)
'
' mean longitude of the Sun
'
L = FNrange(280.461 * rads + .9856474# * rads * d)
'
' mean anomaly of the Sun
'
g = FNrange(357.528 * rads + .9856003# * rads * d)
'
' Ecliptic longitude of the Sun
'
FNsun = FNrange(L + 1.915 * rads * SIN(g) + .02 * rads * SIN(2 * g))
'
' Ecliptic latitude is assumed to be zero by definition
'
END DEF
'
'
'
CLS
'
' get the date and time from the user
'
INPUT " year : ", y
INPUT " month : ", m
INPUT " day : ", day
INPUT "hour UT : ", h
INPUT " minute : ", mins
h = h + mins / 60
d = FNday(y, m, day, h)
'
' Use FNsun to find the ecliptic longitude of the
' Sun
'
lambda = FNsun(d)
'
' Obliquity of the ecliptic
'
obliq = 23.439 * rads - .0000004# * rads * d
'
' Find the RA and DEC of the Sun
'
alpha = FNatn2(COS(obliq) * SIN(lambda), COS(lambda))
delta = FNasin(SIN(obliq) * SIN(lambda))
'
' Find the Earth - Sun distance
'
r = 1.00014 - .01671 * COS(g) - .00014 * COS(2 * g)
'
' Find the Equation of Time
'
equation = (L - alpha) * degs * 4
'
' print results in decimal form
'
PRINT
PRINT "Position of Sun"
PRINT "==============="
PRINT
PRINT USING pr2$; " days : "; d
PRINT USING pr1$; "longitude : "; lambda * degs
PRINT USING pr3$; " RA : "; alpha * degs / 15
PRINT USING pr1$; " DEC : "; delta * degs
PRINT USING pr2$; " distance : "; r
PRINT USING pr1$; "eq time : "; equation
END
'*********************************************************
由於這個原始碼是用非常老的Qbasic語言編寫的,我做了一些修改後, 才能在QB64(https://www.qb64.org) 上執行:
'*********************************************************
' Position-Of-Sun-QB64.bas
'
' This program will calculate the position of the Sun
' using a low precision method found on page C24 of the
' 1996 Astronomical Almanac.
'
' The method is good to 0.01 degrees in the sky over the
' period 1950 to 2050.
'
' QBASIC program by Keith Burnett (kburnett@geocity.com)
' HY: Revised for QB64 by Herong Yang (herong_yang@yahoo.com)
'
' Work in double precision and define some constants
'
DEFDBL A-Z
' HY: Need to declare global variables to be SHARED
'
DIM SHARED pr1$
DIM SHARED pr2$
DIM SHARED pr3$
DIM SHARED pi
DIM SHARED tpi
DIM SHARED twopi
DIM SHARED degs
DIM SHARED rads
pr1$ = "\ \#####.##"
pr2$ = "\ \#####.#####"
pr3$ = "\ \#####.###"
pi = 4 * ATN(1)
tpi = 2 * pi
twopi = tpi
degs = 180 / pi
rads = pi / 180
' HY: Need to generate some junk lines first, since the QB64 only
' HY: show the lower half of the screen
'
SCREEN _NEWIMAGE(800, 660, 256)
CLS
FOR x = 1 TO 21
PRINT "..."
NEXT x
'
' get the date and time from the user
'
INPUT " year : ", y
INPUT " month : ", m
INPUT " day : ", day
INPUT "hour UT : ", h
INPUT " minute : ", mins
h = h + mins / 60
d = FNday(y, m, day, h)
'
' Use FNsun to find the ecliptic longitude of the
' Sun
'
lambda = FNsun(d)
'
' Obliquity of the ecliptic
'
obliq = 23.439 * rads - .0000004# * rads * d
'
' Find the RA and DEC of the Sun
'
alpha = FNatn2(COS(obliq) * SIN(lambda), COS(lambda))
delta = FNasin(SIN(obliq) * SIN(lambda))
'
' Find the Earth - Sun distance
' HY: Need to recalculate g instead of borrow it from FNsun()
'
g = FNrange(357.528 * rads + .9856003# * rads * d)
r = 1.00014 - .01671 * COS(g) - .00014 * COS(2 * g)
'
' Find the Equation of Time
' HY: Need to recalculate L instead of borrow it from FNsun()
'
L = FNrange(280.461 * rads + .9856474# * rads * d)
equation = (L - alpha) * degs * 4
'
' print results in decimal form
'
PRINT
PRINT "Position of Sun"
PRINT "==============="
PRINT
PRINT USING pr2$; " days : "; d
PRINT USING pr1$; "longitude : "; lambda * degs
PRINT USING pr3$; " RA : "; alpha * degs / 15
PRINT USING pr1$; " DEC : "; delta * degs
PRINT USING pr2$; " distance : "; r
PRINT USING pr1$; "eq time : "; equation
END
' HY: Need to move all custom functions to the end
' HY: Need to change DEF statements in to FUNCTION statements
'
' Get the days to J2000
' h is UT in decimal hours
' FNday only works between 1901 to 2099 - see Meeus chapter 7
'
'DEF FNday (y, m, d, h) = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 _
' + 275 * m \ 9 + d - 730531.5 + h / 24
'
FUNCTION FNday (y, m, d, h)
FNday = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 _
+ 275 * m \ 9 + d - 730531.5 + h / 24
END FUNCTION
'
' define some arc cos and arc sin functions and a modified inverse
' tangent function
'
FUNCTION FNacos (x)
s = SQR(1 - x * x)
FNacos = ATN(s / x)
END FUNCTION
FUNCTION FNasin (x)
c = SQR(1 - x * x)
FNasin = ATN(x / c)
END FUNCTION
'
' the atn2 function below returns an angle in the range 0 to two pi
' depending on the signs of x and y.
'
FUNCTION FNatn2 (y, x)
a = ATN(y / x)
IF x < 0 THEN a = a + pi
IF (y < 0) AND (x > 0) THEN a = a + tpi
FNatn2 = a
END FUNCTION
'
' the function below returns the true integer part,
' even for negative numbers
'
FUNCTION FNipart (x)
FNipart = SGN(x) * INT(ABS(x))
END FUNCTION
'
' the function below returns an angle in the range
' 0 to two pi
'
FUNCTION FNrange (x)
b = x / tpi
a = tpi * (b - FNipart(b))
IF a < 0 THEN a = tpi + a
FNrange = a
END FUNCTION
'
' Find the ecliptic longitude of the Sun
'
FUNCTION FNsun (d)
'
' mean longitude of the Sun
'
L = FNrange(280.461 * rads + .9856474# * rads * d)
'
' mean anomaly of the Sun
'
g = FNrange(357.528 * rads + .9856003# * rads * d)
'
' Ecliptic longitude of the Sun
'
FNsun = FNrange(L + 1.915 * rads * SIN(g) + .02 * rads * SIN(2 * g))
'
' Ecliptic latitude is assumed to be zero by definition
'
END FUNCTION
'*********************************************************
下面是首次运行测试的结果:
herong$ cd qb64
herong$ ./qb64 -x Position-Of-Sun-QB64.bas
QB64 Compiler V1.4
Beginning C++ output from QB64 code... first pass finished.
Translating code...
[..................................................] 100%
Compiling C++ code into executable...
Output: Position-Of-Sun-QB64
herong$ ./Position-Of-Sun-QB64
Display Type: Built-In Retina LCD
Resolution: 2880 x 1800 Retina
(You see a new QB64 screen)
(Enter input data as prompted on the new screen)
year : 1997
month : 8
day : 7
hour UT : 11
minute : 0
Position of Sun
===============
days : -877.04167
longitude : 134.98
RA : 9.163
DEC : 16.34
distance : 1.01408
eq time : -5.75
測試結果跟Keith的運行的例子完全吻合。
現在我們可以用Fred的二分點和二至點的數據來驗證Keith的程式:
範例一 - 2001年的春分,"2001= 20 13:31, 21 07:38, 22 23:05, 21 19:22" 的第一個數據。 結果顯示太陽的經角為0.01度,符合誤差範圍:
year : 2001
month : 3
day : 20
hour UT : 13
minute : 31
Position of Sun
===============
days : 444.06319
longitude : 0.01
RA : 0.001
DEC : 0.00
distance : 0.99599
eq time : 1432.56
範例二 - 2021年的夏至,"2021= 20 09:37, 21 03:32, 22 19:21, 21 15:59" 的第二個數據。 結果顯示太陽的經角為90.01度,符合誤差範圍:
year : 2021
month : 6
day : 21
hour UT : 3
minute : 32
Position of Sun
===============
days : 7841.64722
longitude : 90.01
RA : 6.00
DEC : 23.44
distance : 1.01625
eq time : -1.78
範例三 - 2060年的秋分,"2060= 19 20:37, 20 13:44, 22 05:47, 21 03:00" 的第三個數據。 結果顯示太陽的經角為180.00度,完全吻合:
year : 2060
month : 9
day : 22
hour UT : 5
minute : 47
Position of Sun
===============
days :22179.74097
longitude : 180.00
RA : 12.00
DEC : -0.00
distance : 1.00377
eq time : 7.46
範例四 - 2100年的冬至,"2100= 20 13:04, 21 05:32, 22 22:00, 21 19:51" 的第四個數據。 結果顯示太陽的經角為270.85度,有0.15度的誤差。 這在預料之中,因為Keith的程式只能保證在1950到2050年有0.01度的誤差。
year : 2100
month : 12
day : 21
hour UT : 15
minute : 59
Position of Sun
===============
days :36880.16597
longitude : 270.85
RA : 18.062
DEC : -23.42
distance : 0.98376
eq time : 1.50
如果你對《1996 Astronomical Almanac》書中的公式感興趣, 可以在 https://babel.hathitrust.org/cgi/pt?id=mdp.39015036953076 提取PDF圖像。
下面是公式的截屏:
Table of Contents