テイラー展開は関数を多項式で近似する強力な手法ですが、有限次で打ち切ったとき、どの程度の誤差が生じるのかを定量的に評価することが重要です。その評価を可能にするのが テイラーの剰余項 です。
剰余項の理論は、数値計算の誤差評価、級数の収束証明、関数近似の精度保証など、理工学のあらゆる場面で活用されます。本記事では、ラグランジュの剰余項とコーシーの剰余項を導出し、具体的な誤差評価への応用を丁寧に解説します。
本記事の内容
- テイラーの定理の厳密な表現
- ラグランジュの剰余項の導出
- コーシーの剰余項
- 近似誤差の具体的な評価法
- Pythonによる近似精度の可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
テイラーの定理
テイラー多項式
$f(x)$ の $x = a$ の周りの $n$ 次テイラー多項式は:
$$ \begin{equation} T_n(x) = \sum_{k=0}^{n} \frac{f^{(k)}(a)}{k!} (x – a)^k = f(a) + f'(a)(x-a) + \frac{f”(a)}{2!}(x-a)^2 + \cdots + \frac{f^{(n)}(a)}{n!}(x-a)^n \end{equation} $$
テイラーの定理(剰余項付き)
$f$ が区間 $I$ 上で $n+1$ 回微分可能であるとき、$I$ 上の任意の $x$, $a$ に対して:
$$ \begin{equation} f(x) = T_n(x) + R_n(x) \end{equation} $$
ここで $R_n(x)$ は 剰余項(remainder term)で、テイラー多項式と元の関数との誤差を表します。
ラグランジュの剰余項
定理
$f$ が $[a, x]$(または $[x, a]$)上で $n+1$ 回微分可能ならば、$a$ と $x$ の間にある点 $c$ が存在して:
$$ \begin{equation} R_n(x) = \frac{f^{(n+1)}(c)}{(n+1)!} (x – a)^{n+1} \end{equation} $$
これを ラグランジュの剰余項 と呼びます。
導出
$R_n(x) = f(x) – T_n(x)$ とおきます。$R_n$ は次の性質を持ちます:
$$ R_n(a) = R_n'(a) = R_n”(a) = \cdots = R_n^{(n)}(a) = 0 $$
これは $T_n$ が $f$ と $x = a$ で $n$ 次まで一致するように構成されているからです。
補助関数を定義します:
$$ g(t) = f(x) – T_n(x; t) – \frac{R_n(x)}{(x – a)^{n+1}} (x – t)^{n+1} $$
ここで $T_n(x; t)$ は $x = t$ の周りのテイラー多項式です。ただし、より直接的にコーシーの平均値の定理を使う方法で示します。
別証(ロルの定理の繰り返し適用):
$G(t) = f(x) – \sum_{k=0}^{n} \frac{f^{(k)}(t)}{k!}(x-t)^k$ とおくと:
$G(a) = f(x) – T_n(x) = R_n(x)$ であり、$G(x) = f(x) – f(x) = 0$ です。
$G'(t)$ を計算すると、積の微分で多くの項がキャンセルして:
$$ \begin{align} G'(t) &= -\sum_{k=0}^{n} \left[ \frac{f^{(k+1)}(t)}{k!}(x-t)^k – \frac{f^{(k)}(t)}{k!} k(x-t)^{k-1} \right] \\ &= -\frac{f^{(n+1)}(t)}{n!}(x-t)^n \end{align} $$
(テレスコーピング:隣接する項が打ち消し合い、最後の項だけ残る)
ここで補助関数 $H(t) = G(t) – \frac{G(a)}{(x-a)^{n+1}}(x-t)^{n+1}$ を考えると、$H(a) = 0$, $H(x) = 0$ です。
ロルの定理より、$H'(c) = 0$ となる $c$ が $a$ と $x$ の間に存在します:
$$ H'(c) = G'(c) + \frac{G(a)}{(x-a)^{n+1}} (n+1)(x-c)^n = 0 $$
$G'(c)$ を代入して整理すると:
$$ \begin{align} -\frac{f^{(n+1)}(c)}{n!}(x-c)^n + \frac{R_n(x)}{(x-a)^{n+1}} (n+1)(x-c)^n &= 0 \\ R_n(x) &= \frac{f^{(n+1)}(c)}{(n+1)!} (x-a)^{n+1} \end{align} $$
$\square$
誤差の上界
$|f^{(n+1)}(t)| \leq M$ が $a$ と $x$ の間のすべての $t$ で成り立つならば:
$$ \begin{equation} |R_n(x)| \leq \frac{M}{(n+1)!} |x – a|^{n+1} \end{equation} $$
この不等式が実用上最も重要です。$c$ の正確な値は不明でも、$(n+1)$ 階微分の上界 $M$ がわかれば誤差を評価できます。
コーシーの剰余項
ラグランジュの剰余項とは異なる形式の剰余項も存在します。
$$ \begin{equation} R_n(x) = \frac{f^{(n+1)}(c)}{n!} (x – c)^n (x – a) \end{equation} $$
ここで $c$ は $a$ と $x$ の間の点です。コーシーの剰余項は、$c = a + \theta(x-a)$($0 < \theta < 1$)と書けるので:
$$ R_n(x) = \frac{f^{(n+1)}(a + \theta(x-a))}{n!} (1-\theta)^n (x-a)^{n+1} $$
積分形の剰余項
最も正確な表現は積分形です:
$$ \begin{equation} R_n(x) = \frac{1}{n!} \int_a^x (x-t)^n f^{(n+1)}(t) \, dt \end{equation} $$
これは正確な値であり($c$ の存在を仮定しない)、ラグランジュやコーシーの剰余項は、この積分に平均値の定理を適用して得られます。
具体例
例1: $e^x$ のマクローリン展開の誤差
$f(x) = e^x$, $a = 0$ とすると $f^{(n+1)}(x) = e^x$ です。
$0 \leq x \leq 1$ の範囲では $|f^{(n+1)}(c)| = e^c \leq e^1 = e$ なので:
$$ |R_n(x)| \leq \frac{e}{(n+1)!} |x|^{n+1} \leq \frac{e}{(n+1)!} $$
$x = 1$, $n = 5$ のとき:$|R_5(1)| \leq \frac{e}{720} \approx 0.00378$
実際の誤差:$e – T_5(1) = 2.71828… – 2.71667… = 0.00161$
例2: $\sin x$ のマクローリン展開の誤差
$f(x) = \sin x$ の場合、$|f^{(n+1)}(c)| \leq 1$(三角関数は $[-1, 1]$ に値を持つ)なので:
$$ |R_n(x)| \leq \frac{|x|^{n+1}}{(n+1)!} $$
$x = 1$, $n = 7$ のとき:$|R_7(1)| \leq \frac{1}{8!} = \frac{1}{40320} \approx 2.48 \times 10^{-5}$
例3: $\ln(1+x)$ のマクローリン展開の誤差
$f(x) = \ln(1+x)$ のとき:
$$ f^{(n)}(x) = \frac{(-1)^{n-1}(n-1)!}{(1+x)^n} $$
$0 < x \leq 1$ の範囲で:
$$ |R_n(x)| = \left|\frac{(-1)^n}{(n+1)(1+c)^{n+1}}\right| x^{n+1} \leq \frac{x^{n+1}}{n+1} $$
$x = 1$ のとき $|R_n(1)| \leq \frac{1}{n+1}$ で、収束は遅いことがわかります。一方 $x = 0.5$ では $|R_n(0.5)| \leq \frac{0.5^{n+1}}{n+1}$ で急速に収束します。
級数の収束への応用
テイラー級数 $\sum_{k=0}^{\infty} \frac{f^{(k)}(a)}{k!}(x-a)^k$ が $f(x)$ に収束するための十分条件は:
$$ \lim_{n \to \infty} R_n(x) = 0 $$
$e^x$ の場合: 任意の $x$ に対して:
$$ |R_n(x)| \leq \frac{e^{|x|}}{(n+1)!} |x|^{n+1} \to 0 \quad (n \to \infty) $$
($|x|^{n+1}/(n+1)!$ は $n \to \infty$ で $0$ に収束する — 階乗の成長が指数の成長に勝つ)
よって $e^x = \sum_{k=0}^{\infty} \frac{x^k}{k!}$ はすべての $x \in \mathbb{R}$ で成り立ちます。
Pythonでの実装
テイラー多項式の次数による近似精度の比較
import numpy as np
import matplotlib.pyplot as plt
from math import factorial
def taylor_exp(x, a, n):
"""e^x の x=a 周りの n 次テイラー多項式"""
result = np.zeros_like(x, dtype=float)
for k in range(n + 1):
result += np.exp(a) * (x - a)**k / factorial(k)
return result
x = np.linspace(-3, 5, 500)
a = 0 # マクローリン展開
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
# 左: テイラー多項式の比較
axes[0].plot(x, np.exp(x), 'k-', linewidth=3, label=r'$e^x$(真値)')
colors = plt.cm.viridis(np.linspace(0, 0.8, 6))
for i, n in enumerate([1, 2, 3, 5, 8, 12]):
axes[0].plot(x, taylor_exp(x, a, n), '--', color=colors[i],
linewidth=1.5, label=f'$T_{{{n}}}(x)$')
axes[0].set_xlabel('x', fontsize=12)
axes[0].set_ylabel('y', fontsize=12)
axes[0].set_title(r'$e^x$ のテイラー多項式近似', fontsize=14)
axes[0].set_ylim(-5, 30)
axes[0].legend(fontsize=9, ncol=2)
axes[0].grid(True, alpha=0.3)
# 右: 誤差の対数プロット
for i, n in enumerate([1, 2, 3, 5, 8, 12]):
error = np.abs(np.exp(x) - taylor_exp(x, a, n))
error[error < 1e-16] = 1e-16 # ゼロ除算防止
axes[1].semilogy(x, error, '--', color=colors[i],
linewidth=1.5, label=f'$|R_{{{n}}}(x)|$')
axes[1].set_xlabel('x', fontsize=12)
axes[1].set_ylabel('|誤差|', fontsize=12)
axes[1].set_title('近似誤差(対数スケール)', fontsize=14)
axes[1].legend(fontsize=9, ncol=2)
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
複数の関数での収束速度の比較
import numpy as np
import matplotlib.pyplot as plt
from math import factorial
def taylor_sin(x, n_terms):
"""sin(x) のマクローリン展開(n_terms 項)"""
result = np.zeros_like(x, dtype=float)
for k in range(n_terms):
result += (-1)**k * x**(2*k+1) / factorial(2*k+1)
return result
def taylor_ln1px(x, n_terms):
"""ln(1+x) のマクローリン展開(n_terms 項)"""
result = np.zeros_like(x, dtype=float)
for k in range(1, n_terms + 1):
result += (-1)**(k+1) * x**k / k
return result
def taylor_exp_func(x, n_terms):
"""e^x のマクローリン展開(n_terms 項)"""
result = np.zeros_like(x, dtype=float)
for k in range(n_terms):
result += x**k / factorial(k)
return result
# 各点 x での収束速度
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
n_range = np.arange(1, 20)
# e^x at x=1
errors_exp = [abs(np.exp(1) - sum(1.0/factorial(k) for k in range(n+1))) for n in n_range]
axes[0].semilogy(n_range, errors_exp, 'bo-', linewidth=2, markersize=5)
upper_bound = [np.exp(1) / factorial(n+1) for n in n_range]
axes[0].semilogy(n_range, upper_bound, 'r--', linewidth=2, label='上界')
axes[0].set_xlabel('次数 n', fontsize=12)
axes[0].set_ylabel('|誤差|', fontsize=12)
axes[0].set_title(r'$e^x$ at $x=1$', fontsize=14)
axes[0].legend(fontsize=11)
axes[0].grid(True, alpha=0.3)
# sin(x) at x=1
errors_sin = []
for n in n_range:
approx = sum((-1)**k / factorial(2*k+1) for k in range((n+1)//2))
errors_sin.append(abs(np.sin(1) - approx))
errors_sin = [max(e, 1e-17) for e in errors_sin]
axes[1].semilogy(n_range, errors_sin, 'bo-', linewidth=2, markersize=5)
axes[1].set_xlabel('項数', fontsize=12)
axes[1].set_ylabel('|誤差|', fontsize=12)
axes[1].set_title(r'$\sin x$ at $x=1$', fontsize=14)
axes[1].grid(True, alpha=0.3)
# ln(1+x) at x=0.5 and x=1
errors_ln_05 = []
errors_ln_1 = []
for n in n_range:
approx_05 = sum((-1)**(k+1) * 0.5**k / k for k in range(1, n+1))
approx_1 = sum((-1)**(k+1) / k for k in range(1, n+1))
errors_ln_05.append(abs(np.log(1.5) - approx_05))
errors_ln_1.append(abs(np.log(2) - approx_1))
errors_ln_05 = [max(e, 1e-17) for e in errors_ln_05]
errors_ln_1 = [max(e, 1e-17) for e in errors_ln_1]
axes[2].semilogy(n_range, errors_ln_05, 'bo-', linewidth=2, markersize=5, label='x=0.5')
axes[2].semilogy(n_range, errors_ln_1, 'rs-', linewidth=2, markersize=5, label='x=1')
axes[2].set_xlabel('項数 n', fontsize=12)
axes[2].set_ylabel('|誤差|', fontsize=12)
axes[2].set_title(r'$\ln(1+x)$', fontsize=14)
axes[2].legend(fontsize=11)
axes[2].grid(True, alpha=0.3)
plt.suptitle('テイラー展開の収束速度の比較', fontsize=16)
plt.tight_layout()
plt.show()
剰余項の上界と実際の誤差
import numpy as np
import matplotlib.pyplot as plt
from math import factorial
# sin(x) のテイラー展開の誤差
# |R_n(x)| <= |x|^{n+1} / (n+1)!
x_vals = np.linspace(0, 4, 200)
fig, ax = plt.subplots(figsize=(10, 6))
for n in [1, 3, 5, 7, 9]:
# 実際の誤差
taylor = sum((-1)**k * x_vals**(2*k+1) / factorial(2*k+1) for k in range((n+1)//2))
actual_error = np.abs(np.sin(x_vals) - taylor)
actual_error[actual_error < 1e-16] = 1e-16
# ラグランジュ上界
upper_bound = x_vals**(n+1) / factorial(n+1)
ax.semilogy(x_vals, actual_error, '-', linewidth=2, label=f'実誤差 n={n}')
ax.semilogy(x_vals, upper_bound, '--', linewidth=1, alpha=0.5, label=f'上界 n={n}')
ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('誤差', fontsize=12)
ax.set_title(r'$\sin x$ の剰余項: 実際の誤差 vs ラグランジュの上界', fontsize=14)
ax.legend(fontsize=9, ncol=2, loc='lower right')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
まとめ
本記事では、テイラー展開の剰余項について解説しました。
- テイラーの定理: $f(x) = T_n(x) + R_n(x)$(テイラー多項式+剰余項)
- ラグランジュの剰余項: $R_n(x) = \frac{f^{(n+1)}(c)}{(n+1)!}(x-a)^{n+1}$($c$ は $a$ と $x$ の間)
- 誤差の上界: $|R_n(x)| \leq \frac{M}{(n+1)!}|x-a|^{n+1}$($M$ は $(n+1)$ 階微分の上界)
- 収束速度: $e^x$ や $\sin x$ は急速に収束するが、$\ln(1+x)$ の $x = 1$ での収束は遅い
- 積分形の剰余項 が最も正確な表現で、他の形式はそこから導かれる
- 階乗 $(n+1)!$ の急成長が近似精度を保証する鍵
次のステップとして、以下の記事も参考にしてください。
- テイラー展開・マクローリン展開 — テイラー展開の基本
- ロピタルの定理 — テイラー展開を使った極限の計算