Kepler の方程式は文献に現れた初めての超越方程式であり、 これまでに何百という解法が考えられてきたそうである (平凡社百科事典の記述 (by 堀 源一郎) による)。
私の記憶が確かならば、 中野主一氏の天文計算プログラムでも、 反復法で解いていた。 今度、チェックしよう。
(平均近点角),
(離心率) が与えられているとき、
反復法で解く場合、初期値が必要になるが、
よほど離心率が大きく ( に近く) ない限り、
を初期値に選ぶので良いと思われる。
,
とすると、
.
b
Mathematicaで |
EE=2/10 m=8/10 FindRoot[x==m+EE*Sin[x],{x,1},WorkingPrecision->100] 0.96433388769522264457506271899845052028615328006880 (改行) 70848686011389985763852645291991226699739659693633 |
[ |
l]Cで
/* * solve-kepler.c */ #include <stdio.h> #include <math.h> int verbose = 1; int maxcount = 0; double M, e; double f(double E) { return E - e * sin(E) - M; } double df(double E) { return 1.0 - e * cos(E); } typedef double func(double); #define MAX_ITER 100 // Newton法で f(x)=0 の x0 の近くの解を求める double newton(func f, double x0, double eps) { int i; double x, dx; x = x0; for (i = 0; i <= MAX_ITER; i++) { dx = f(x) / df(x); x -= dx; if (fabs(dx) < eps) break; } if (i > maxcount) maxcount = i; /* 簡単に報告 */ if (fabs(dx) > eps) printf("%d回で収束しなかった。dx=%g\n", MAX_ITER, dx); else if (verbose) printf("x0=%g, count=%d, dx=%g\n", x0, i, dx); /* 最後にもう1回反復 */ x -= f(x) / df(x); return x; } int main(void) { double E; int i, n; double pi, dM; pi = 4.0 * atan(1.0); /* 区間 [0,2π] を 100 等分 */ n = 100; dM =2 * pi / n; /* 離心率 */ printf("e="); scanf("%lf", &e); for (i = 0; i <= n; i++) { M = i * dM; /* M = E - e * sin(E) を解く */ /* f(E) = E - e * sin(E) - M */ E = newton(f, M, 1e-14); printf("%f %f\n", M, E); } printf("max count=%d\n", maxcount); M = 0.8; e = 0.2; E = newton(f, M, 1e-12); printf("e=%g, M=%g, E=%17.15f\n", e, M, E); return 0; } |