forked from yuangu/sxtwl_cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSSQ.cpp
More file actions
374 lines (325 loc) · 16.5 KB
/
SSQ.cpp
File metadata and controls
374 lines (325 loc) · 16.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#include "SSQ.h"
#include <math.h>
#include "const.h"
#include "eph.h"
SSQ::SSQ()
{
std::string suoS = "", qiS = "";
// 619-01-21开始16598个朔日修正表 d0=1947168
suoS = "EqoFscDcrFpmEsF2DfFideFelFpFfFfFiaipqti1ksttikptikqckstekqttgkqttgkqteksttikptikq2fjstgjqttjkqttgkqt";
suoS += "ekstfkptikq2tijstgjiFkirFsAeACoFsiDaDiADc1AFbBfgdfikijFifegF1FhaikgFag1E2btaieeibggiffdeigFfqDfaiBkF";
suoS += "1kEaikhkigeidhhdiegcFfakF1ggkidbiaedksaFffckekidhhdhdikcikiakicjF1deedFhFccgicdekgiFbiaikcfi1kbFibef";
suoS += "gEgFdcFkFeFkdcfkF1kfkcickEiFkDacFiEfbiaejcFfffkhkdgkaiei1ehigikhdFikfckF1dhhdikcfgjikhfjicjicgiehdik";
suoS += "cikggcifgiejF1jkieFhegikggcikFegiegkfjebhigikggcikdgkaFkijcfkcikfkcifikiggkaeeigefkcdfcfkhkdgkegieid";
suoS += "hijcFfakhfgeidieidiegikhfkfckfcjbdehdikggikgkfkicjicjF1dbidikFiggcifgiejkiegkigcdiegfggcikdbgfgefjF1";
suoS += "kfegikggcikdgFkeeijcfkcikfkekcikdgkabhkFikaffcfkhkdgkegbiaekfkiakicjhfgqdq2fkiakgkfkhfkfcjiekgFebicg";
suoS += "gbedF1jikejbbbiakgbgkacgiejkijjgigfiakggfggcibFifjefjF1kfekdgjcibFeFkijcfkfhkfkeaieigekgbhkfikidfcje";
suoS += "aibgekgdkiffiffkiakF1jhbakgdki1dj1ikfkicjicjieeFkgdkicggkighdF1jfgkgfgbdkicggfggkidFkiekgijkeigfiski";
suoS += "ggfaidheigF1jekijcikickiggkidhhdbgcfkFikikhkigeidieFikggikhkffaffijhidhhakgdkhkijF1kiakF1kfheakgdkif";
suoS += "iggkigicjiejkieedikgdfcggkigieeiejfgkgkigbgikicggkiaideeijkefjeijikhkiggkiaidheigcikaikffikijgkiahi1";
suoS += "hhdikgjfifaakekighie1hiaikggikhkffakicjhiahaikggikhkijF1kfejfeFhidikggiffiggkigicjiekgieeigikggiffig";
suoS += "gkidheigkgfjkeigiegikifiggkidhedeijcfkFikikhkiggkidhh1ehigcikaffkhkiggkidhh1hhigikekfiFkFikcidhh1hit";
suoS += "cikggikhkfkicjicghiediaikggikhkijbjfejfeFhaikggifikiggkigiejkikgkgieeigikggiffiggkigieeigekijcijikgg";
suoS += "ifikiggkideedeijkefkfckikhkiggkidhh1ehijcikaffkhkiggkidhh1hhigikhkikFikfckcidhh1hiaikgjikhfjicjicgie";
suoS += "hdikcikggifikigiejfejkieFhegikggifikiggfghigkfjeijkhigikggifikiggkigieeijcijcikfksikifikiggkidehdeij";
suoS += "cfdckikhkiggkhghh1ehijikifffffkhsFngErD1pAfBoDd1BlEtFqA2AqoEpDqElAEsEeB2BmADlDkqBtC1FnEpDqnEmFsFsAFn";
suoS += "llBbFmDsDiCtDmAB2BmtCgpEplCpAEiBiEoFqFtEqsDcCnFtADnFlEgdkEgmEtEsCtDmADqFtAFrAtEcCqAE1BoFqC1F1DrFtBmF";
suoS += "tAC2ACnFaoCgADcADcCcFfoFtDlAFgmFqBq2bpEoAEmkqnEeCtAE1bAEqgDfFfCrgEcBrACfAAABqAAB1AAClEnFeCtCgAADqDoB";
suoS += "mtAAACbFiAAADsEtBqAB2FsDqpFqEmFsCeDtFlCeDtoEpClEqAAFrAFoCgFmFsFqEnAEcCqFeCtFtEnAEeFtAAEkFnErAABbFkAD";
suoS += "nAAeCtFeAfBoAEpFtAABtFqAApDcCGJ";
//1645-09-23开始7567个节气修正表
qiS = "FrcFs22AFsckF2tsDtFqEtF1posFdFgiFseFtmelpsEfhkF2anmelpFlF1ikrotcnEqEq2FfqmcDsrFor22FgFrcgDscFs22FgEe";
qiS += "FtE2sfFs22sCoEsaF2tsD1FpeE2eFsssEciFsFnmelpFcFhkF2tcnEqEpFgkrotcnEqrEtFermcDsrE222FgBmcmr22DaEfnaF22";
qiS += "2sD1FpeForeF2tssEfiFpEoeFssD1iFstEqFppDgFstcnEqEpFg11FscnEqrAoAF2ClAEsDmDtCtBaDlAFbAEpAAAAAD2FgBiBqo";
qiS += "BbnBaBoAAAAAAAEgDqAdBqAFrBaBoACdAAf1AACgAAAeBbCamDgEifAE2AABa1C1BgFdiAAACoCeE1ADiEifDaAEqAAFe1AcFbcA";
qiS += "AAAAF1iFaAAACpACmFmAAAAAAAACrDaAAADG0";
SB = jieya(suoS); //定朔修正表解压
QB = jieya(qiS); //定气修正表解压
//朔直线拟合参数
long double suoKBTmp[] = {
1457698.231017,29.53067166, // -721-12-17 h=0.00032 古历·春秋
1546082.512234,29.53085106, // -479-12-11 h=0.00053 古历·战国
1640640.735300,29.53060000, // -221-10-31 h=0.01010 古历·秦汉
1642472.151543,29.53085439, // -216-11-04 h=0.00040 古历·秦汉
1683430.509300,29.53086148, // -104-12-25 h=0.00313 汉书·律历志(太初历)平气平朔
1752148.041079,29.53085097, // 85-02-13 h=0.00049 后汉书·律历志(四分历)
1807665.420323,29.53059851, // 237-02-12 h=0.00033 晋书·律历志(景初历)
1883618.114100,29.53060000, // 445-01-24 h=0.00030 宋书·律历志(何承天元嘉历)
1907360.704700,29.53060000, // 510-01-26 h=0.00030 宋书·律历志(祖冲之大明历)
1936596.224900,29.53060000, // 590-02-10 h=0.01010 随书·律历志(开皇历)
1939135.675300,29.53060000, // 597-01-24 h=0.00890 随书·律历志(大业历)
1947168.00// 619-01-21
};
suoKB = new std::vector<long double>(suoKBTmp, suoKBTmp + sizeof(suoKBTmp) / sizeof(long double));
long double qiKBTmp[] = {
1640650.479938,15.21842500, // -221-11-09 h=0.01709 古历·秦汉
1642476.703182,15.21874996, // -216-11-09 h=0.01557 古历·秦汉
1683430.515601,15.218750011, // -104-12-25 h=0.01560 汉书·律历志(太初历)平气平朔 回归年=365.25000
1752157.640664,15.218749978, // 85-02-23 h=0.01559 后汉书·律历志(四分历) 回归年=365.25000
1807675.003759,15.218620279, // 237-02-22 h=0.00010 晋书·律历志(景初历) 回归年=365.24689
1883627.765182,15.218612292, // 445-02-03 h=0.00026 宋书·律历志(何承天元嘉历) 回归年=365.24670
1907369.128100,15.218449176, // 510-02-03 h=0.00027 宋书·律历志(祖冲之大明历) 回归年=365.24278
1936603.140413,15.218425000, // 590-02-17 h=0.00149 随书·律历志(开皇历) 回归年=365.24220
1939145.524180,15.218466998, // 597-02-03 h=0.00121 随书·律历志(大业历) 回归年=365.24321
1947180.798300,15.218524844, // 619-02-03 h=0.00052 新唐书·历志(戊寅元历)平气定朔 回归年=365.24460
1964362.041824,15.218533526, // 666-02-17 h=0.00059 新唐书·历志(麟德历) 回归年=365.24480
1987372.340971,15.218513908, // 729-02-16 h=0.00096 新唐书·历志(大衍历,至德历) 回归年=365.24433
1999653.819126,15.218530782, // 762-10-03 h=0.00093 新唐书·历志(五纪历) 回归年=365.24474
2007445.469786,15.218535181, // 784-02-01 h=0.00059 新唐书·历志(正元历,观象历) 回归年=365.24484
2021324.917146,15.218526248, // 822-02-01 h=0.00022 新唐书·历志(宣明历) 回归年=365.24463
2047257.232342,15.218519654, // 893-01-31 h=0.00015 新唐书·历志(崇玄历) 回归年=365.24447
2070282.898213,15.218425000, // 956-02-16 h=0.00149 旧五代·历志(钦天历) 回归年=365.24220
2073204.872850,15.218515221, // 964-02-16 h=0.00166 宋史·律历志(应天历) 回归年=365.24437
2080144.500926,15.218530782, // 983-02-16 h=0.00093 宋史·律历志(乾元历) 回归年=365.24474
2086703.688963,15.218523776, // 1001-01-31 h=0.00067 宋史·律历志(仪天历,崇天历) 回归年=365.24457
2110033.182763,15.218425000, // 1064-12-15 h=0.00669 宋史·律历志(明天历) 回归年=365.24220
2111190.300888,15.218425000, // 1068-02-15 h=0.00149 宋史·律历志(崇天历) 回归年=365.24220
2113731.271005,15.218515671, // 1075-01-30 h=0.00038 李锐补修(奉元历) 回归年=365.24438
2120670.840263,15.218425000, // 1094-01-30 h=0.00149 宋史·律历志 回归年=365.24220
2123973.309063,15.218425000, // 1103-02-14 h=0.00669 李锐补修(占天历) 回归年=365.24220
2125068.997336,15.218477932, // 1106-02-14 h=0.00056 宋史·律历志(纪元历) 回归年=365.24347
2136026.312633,15.218472436, // 1136-02-14 h=0.00088 宋史·律历志(统元历,乾道历,淳熙历) 回归年=365.24334
2156099.495538,15.218425000, // 1191-01-29 h=0.00149 宋史·律历志(会元历) 回归年=365.24220
2159021.324663,15.218425000, // 1199-01-29 h=0.00149 宋史·律历志(统天历) 回归年=365.24220
2162308.575254,15.218461742, // 1208-01-30 h=0.00146 宋史·律历志(开禧历) 回归年=365.24308
2178485.706538,15.218425000, // 1252-05-15 h=0.04606 淳祐历 回归年=365.24220
2178759.662849,15.218445786, // 1253-02-13 h=0.00231 会天历 回归年=365.24270
2185334.020800,15.218425000, // 1271-02-13 h=0.00520 宋史·律历志(成天历) 回归年=365.24220
2187525.481425,15.218425000, // 1277-02-12 h=0.00520 本天历 回归年=365.24220
2188621.191481,15.218437494, // 1280-02-13 h=0.00015 元史·历志(郭守敬授时历) 回归年=365.24250
2322147.76// 1645-09-21
};
qiKB = new std::vector<long double>(qiKBTmp, qiKBTmp + sizeof(qiKBTmp) / sizeof(long double));
}
SSQ::~SSQ()
{
delete suoKB;
delete qiKB;
}
void str_replace(std::string & str, const std::string strsrc, const std::string strdst)
{
std::string::size_type pos = 0;//位置
std::string::size_type srclen = strsrc.size();//要替换的字符串大小
std::string::size_type dstlen = strdst.size();//目标字符串大小
while ((pos = str.find(strsrc, pos)) != std::string::npos)
{
str.replace(pos, srclen, strdst);
pos += dstlen;
}
}
std::string SSQ::jieya(std::string s) { //气朔解压缩
std::string o = "0000000000", o2 = o + o;
str_replace(s, "J", "00");
str_replace(s, "I", "000");
str_replace(s, "H", "0000");
str_replace(s, "G", "00000");
str_replace(s, "t", "02");
str_replace(s, "s", "002");
str_replace(s, "r", "0002");
str_replace(s, "q", "00002");
str_replace(s, "p", "000002");
str_replace(s, "o", "0000002");
str_replace(s, "n", "00000002");
str_replace(s, "m", "000000002");
str_replace(s, "l", "0000000002");
str_replace(s, "k", "01");
str_replace(s, "j", "0101");
str_replace(s, "i", "001");
str_replace(s, "h", "001001");
str_replace(s, "g", "0001");
str_replace(s, "f", "00001");
str_replace(s, "e", "000001");
str_replace(s, "d", "0000001");
str_replace(s, "c", "00000001");
str_replace(s, "b", "000000001");
str_replace(s, "a", "0000000001");
str_replace(s, "A", o2 + o2 + o2);
str_replace(s, "B", o2 + o2 + o);
str_replace(s, "C", o2 + o2);
str_replace(s, "D", o2 + o);
str_replace(s, "E", o2);
str_replace(s, "F", o);
return s;
}
int SSQ::calc(long double jd, QSType qs)
{
jd += 2451545;
int i;
long double D;
std::string n;
std::vector<long double> B = *suoKB;
long double pc = 14;
//如果查的是气朔
if (qs == QType)
{
B = *qiKB, pc = 7;
}
long double f1 = B[0] - pc, f2 = B[B.size() - 1] - pc, f3 = 2436935;
if (jd < f1 || jd >= f3)
{
//平气朔表中首个之前,使用现代天文算法。1960.1.1以后,使用现代天文算法 (这一部分调用了qi_high和so_high,所以需星历表支持)
if (qs == QType)
{
return floor(qi_high(floor((jd + pc - 2451259) / 365.2422 * 24) * PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算
}
else
{
return floor(so_high(floor((jd + pc - 2451551) / 29.5306) * PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算
}
}
if (jd >= f1 && jd < f2) { //平气或平朔
for (i = 0; i < B.size(); i += 2) if (jd + pc < B[i + 2]) break;
D = B[i] + B[i + 1] * floor((jd + pc - B[i]) / B[i + 1]);
D = floor(D + 0.5);
if (D == 1683460) D++; //如果使用太初历计算-103年1月24日的朔日,结果得到的是23日,这里修正为24日(实历)。修正后仍不影响-103的无中置闰。如果使用秦汉历,得到的是24日,本行D不会被执行。
return D - 2451545;
}
if (jd >= f2 && jd < f3) { //定气或定朔
if (qs == QType) {
D = floor(qi_low(floor((jd + pc - 2451259) / 365.2422 * 24) * PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算
n = QB.substr(floor((jd - f2) / 365.2422 * 24), 1); //找定气修正值
}
else {
D = floor(so_low(floor((jd + pc - 2451551) / 29.5306) * PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算
n = SB.substr(floor((jd - f2) / 29.5306), 1); //找定朔修正值
}
if (n == "1") return D + 1;
if (n == "2") return D - 1;
return D;
}
return 0;
}
long double SSQ::qi_high(long double W)
{
long double t = XL::S_aLon_t2(W) * 36525;
t = t - dt_T(t) + 8.0 / 24.0;
long double v = fmod(t + 0.5, 1) * 86400;
if (v < 1200 || v >86400 - 1200) t = XL::S_aLon_t(W) * 36525 - dt_T(t) + 8.0 / 24.0;
return t;
}
long double SSQ::so_high(long double W)
{ //较高精度朔
long double t = XL::MS_aLon_t2(W) * 36525;
t = t - dt_T(t) + 8.0 / 24.0;
long double v = fmod(t + 0.5, 1) * 86400;
if (v < 1800 || v >86400 - 1800) t = XL::MS_aLon_t(W) * 36525 - dt_T(t) + 8.0 / 24.0;
return t;
}
long double SSQ::so_low(long double W) { //低精度定朔计算,在2000年至600,误差在2小时以内(仍比古代日历精准很多)
long double v = 7771.37714500204;
long double t = (W + 1.08472) / v, L;
t -= (-0.0000331*t*t
+ 0.10976 *cos(0.785 + 8328.6914*t)
+ 0.02224 *cos(0.187 + 7214.0629*t)
- 0.03342 *cos(4.669 + 628.3076*t)) / v
+ (32 * (t + 1.8)*(t + 1.8) - 20) / 86400 / 36525;
return t * 36525 + 8.0 / 24.0;
}
long double SSQ::qi_low(long double W) { //最大误差小于30分钟,平均5分
long double t, L, v = 628.3319653318;
t = (W - 4.895062166) / v; //第一次估算,误差2天以内
t -= (53 * t*t + 334116 * cos(4.67 + 628.307585*t) + 2061 * cos(2.678 + 628.3076*t)*t) / v / 10000000; //第二次估算,误差2小时以内
L = 48950621.66 + 6283319653.318*t + 53 * t*t //平黄经
+ 334166 * cos(4.669257 + 628.307585*t) //地球椭圆轨道级数展开
+ 3489 * cos(4.6261 + 1256.61517*t) //地球椭圆轨道级数展开
+ 2060.6 * cos(2.67823 + 628.307585*t) * t //一次泊松项
- 994 - 834 * sin(2.1824 - 33.75705*t); //光行差与章动修正
t -= (L / 10000000 - W) / 628.332 + (32 * (t + 1.8)*(t + 1.8) - 20) / 86400 / 36525;
return t * 36525 + 8.0 / 24.0;
}
//农历排月序计算,可定出农历,有效范围:两个冬至之间(冬至一 <= d < 冬至二)
void SSQ::calcY(int jd) {
std::vector<long double>& A = ZQ;
std::vector<int>& B = HS; //中气表,日月合朔表(整日)
int i, k;
long double W, w;
//该年的气
W = int2((jd - 355 + 183) / 365.2422)*365.2422 + 355; //355是2000.12冬至,得到较靠近jd的冬至估计值
if (calc(W, QType) > jd)
{
W -= 365.2422;
}
//25个节气时刻(北京时间),从冬至开始到下一个冬至以后;
A.clear();
for (i = 0; i < 25; i++)
{
int t = calc(W + 15.2184*i, QType);
A.push_back(t);
}
ZQ_pe1 = calc(W - 15.2, QType); ZQ_pe2 = calc(W - 30.4, QType); //补算二气,确保一年中所有月份的“气”全部被计算在内
//今年"首朔"的日月黄经差w
w = calc(A[0], SType); //求较靠近冬至的朔日
if (w > A[0])
{
w -= 29.53;
}
//该年所有朔,包含14个月的始末
B.clear();
for (i = 0; i < 15; i++)
{
B.push_back( calc(w + 29.5306*i, SType) );
}
//月大小
leap = 0;
dx.clear();
ym.clear();
for (i = 0; i < 14; i++) {
dx.push_back( HS[i + 1] - HS[i] ); //月大小
ym.push_back(i); //月序初始化
}
//-721年至-104年的后九月及月建问题,与朔有关,与气无关
int YY = int2((ZQ[0] + 10 + 180) / 365.2422) + 2000; //确定年份
if (YY >= -721 && YY <= -104) {
int ns[12];
int yy;
for (i = 0; i < 3; i++) {
yy = YY + i - 1;
//颁行历年首, 闰月名称, 月建
if (yy >= -721)
{
ns[i] = calc(1457698 - J2000 + int2(0.342 + (yy + 721)*12.368422)*29.5306, SType);
//ns[i + 3] = '十三';
ns[i + 6] = 2; //春秋历,ly为-722.12.17
}
if (yy >= -479)
{
ns[i] = calc(1546083 - J2000 + int2(0.500 + (yy + 479)*12.368422)*29.5306, SType);
//ns[i + 3] = '十三';
ns[i + 6] = 2; //战国历,ly为-480.12.11
}
if (yy >= -220) {
ns[i] = calc(1640641 - J2000 + int2(0.866 + (yy + 220)*12.369000)*29.5306, SType);
// ns[i + 3] = '后九';
ns[i + 6] = 11; //秦汉历,ly为-221.10.31
}
}
int nn, f1;
for (i = 0; i < 14; i++) {
for (nn = 2; nn >= 0; nn--) if (HS[i] >= ns[nn]) break;
f1 = int2((HS[i] - ns[nn] + 15) / 29.5306); //该月积数
if (f1 < 12) ym[i] = (f1 + ns[nn + 6]) % 12; else ym[i] = ns[nn + 3];
}
return;
}
//无中气置闰法确定闰月,(气朔结合法,数据源需有冬至开始的的气和朔)
if (B[13] <= A[24]) { //第13月的月末没有超过冬至(不含冬至),说明今年含有13个月
for (i = 1; B[i + 1] > A[2 * i] && i < 13; i++); //在13个月中找第1个没有中气的月份
leap = i;
for (; i < 14; i++) ym[i]--;
}
//名称转换(月建别名)
for (i = 0; i < 14; i++) {
int Dm = HS[i] + J2000, v2 = ym[i]; //Dm初一的儒略日,v2为月建序号
int mc = v2 % 12; //月建对应的默认月名称:建子十一,建丑十二,建寅为正……
if (Dm >= 1724360 && Dm <= 1729794) mc = (v2 + 1) % 12; // 8.01.15至 23.12.02 建子为十二,其它顺推
else if (Dm >= 1807724 && Dm <= 1808699) mc = (v2 + 1) % 12; //237.04.12至239.12.13 建子为十二,其它顺推
else if (Dm >= 1999349 && Dm <= 1999467) mc = (v2 + 2) % 12; //761.12.02至762.03.30 建子为正月,其它顺推
else if (Dm >= 1973067 && Dm <= 1977052) { if (v2 % 12 == 0) mc = 2; if (v2 == 2) mc = 2; } //689.12.18至700.11.15 建子为正月,建寅为一月,其它不变
if (Dm == 1729794 || Dm == 1808699)
{
mc = 12;
// mc = '拾贰'; //239.12.13及23.12.02均为十二月,为避免两个连续十二月,此处改名
}
ym[i] = mc;
}
}