コンテンツにスキップ

条件数と安定性:前進誤差と後退誤差で数値計算の精度を読む

対象読者: 本テーマ第 1 章(浮動小数点数と丸め誤差)と、学部の多変数微分(ヤコビ行列・陰関数定理)、平均値の定理を学んだ人。行列のノルムの定義は既知とし、数値解析の他の知識は仮定しません。

前提となる記事:浮動小数点数と丸め誤差:IEEE 754・標準モデル・和と Horner 法の誤差解析、多変数関数の微分と偏微分:微分とは「一次近似」のことである

生 Markdown

計算機で計算した答えが期待とずれたとき、原因は 2 通り考えられます。計算のやり方が悪いのか、それとも問題そのものが入力のわずかな違いに敏感すぎるのか、です。この記事では、この 2 つを切り分けるための物差しを作ります。読み終えると、答えの誤差が「問題のせい」か「計算法のせい」かを見分け、後者なら式の書き換えで直せる理由を説明できるようになります。

  • 数値計算の誤差を、問題の感度(条件数。入力の誤差が答えで何倍に拡大されるかを表す数)とアルゴリズムの良さ(後退誤差。入力をどれだけずらしたことにすれば計算値が正確な答えになるか)の 2 つに分けて考えます。前者は数学の問題そのものの性質で、どんなアルゴリズムでも変えられません。
  • 微分可能な問題 ff の相対条件数は κ(x)=∥J(x)∥∥x∥/∥f(x)∥\kappa(x)=\|J(x)\|\|x\|/\|f(x)\|(JJ はヤコビ行列)、1 変数なら ∣xf′(x)/f(x)∣|xf'(x)/f(x)| です。成分ごとの相対摂動に対する条件数は ∑i∣xi ∂if(x)∣/∣f(x)∣\sum_i|x_i\,\partial_if(x)|/|f(x)| です。
  • 計算値 y^\hat y が「少しずらした入力 x+Δxx+\Delta x に対する正確な答え」と書けるとき、その Δx\Delta x の大きさが後退誤差です。前進誤差 ≲ 条件数 × 後退誤差 が成り立ち、1 次の評価だけでなく、平均値不等式による非漸近の評価も証明できます。
  • 浮動小数点数の四則・内積・Horner 法(多項式の値を、かけ算とたし算の繰り返しで求める方法)は後退安定(計算値が、少しずらした入力の正確な答えになっていること)です。多項式の単根は係数の摂動に対して −εq(x∗)/p′(x∗)-\varepsilon q(x^\ast)/p'(x^\ast) だけ動き(陰関数定理。方程式の解が係数の変化に応じてなめらかに動くことを保証する定理)、Wilkinson の多項式では係数を 2−232^{-23} 動かすだけで 10 個の根が複素数になります。
  • 2 次方程式の解の公式、log⁡(1+x)\log(1+x)、分散の 1 パス公式は、条件のよい問題を不安定なアルゴリズムで解いている例です。式を書き換えると誤差は単位丸め程度に戻ります。

浮動小数点数と丸め誤差の章の最後で、Horner 法の計算値は「各係数を相対 γ2n\gamma_{2n} だけ動かした多項式の正確な値」であることを示しました(定理 6.1[浮動小数点数と丸め誤差])。それでも (x−1)10(x-1)^{10} を展開した多項式を x=1.01x=1.01 で計算すると、答えは 1 桁も信頼できません。Horner 法は悪くないのに、答えは悪い。この食い違いを説明するのがこの記事の主題です。

答えの誤差(前進誤差)は、2 つの量の積で決まります。

  1. アルゴリズムが入力をどれだけ「ずらしたことにしたか」(後退誤差)。これはアルゴリズムの性質です。
  2. 入力のずれが答えにどれだけ拡大されるか(条件数)。これは問題の性質です。

この分け方の利点は、それぞれを別々に、しかも定理として評価できることです。後退誤差は浮動小数点数の章のような丸め誤差の解析で、条件数は微分の計算で求まります。そして、条件数が大きい問題で答えが悪いのはアルゴリズムのせいではなく、条件数が小さいのに答えが悪いならアルゴリズムを替えるべきだ、と判断できます。

以下、Rn\mathbb{R}^n のノルムはユークリッドノルム ∥⋅∥\|\cdot\|、行列のノルムはそれから誘導される作用素ノルム ∥J∥=sup⁡h≠0∥Jh∥/∥h∥\|J\|=\sup_{\boldsymbol{h}\ne\boldsymbol{0}}\|J\boldsymbol{h}\|/\|\boldsymbol{h}\| とします。成分ごとの相対摂動の大きさを測るため、x∈Rn\boldsymbol{x}\in\mathbb{R}^n と Δx\Delta\boldsymbol{x} について

ηx(Δx)=min⁡{η≥0:∣Δxi∣≤η∣xi∣ (i=1,…,n)}\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})=\min\{\eta\ge0:|\Delta x_i|\le\eta|x_i|\ (i=1,\ldots,n)\}

(そのような η\eta がなければ ∞\infty。xi=0x_i=0 の成分は動かせない)とおきます。

ηx\eta_{\boldsymbol{x}} を使うのは、浮動小数点数では各成分が互いに独立に相対 uu 程度ずつ丸められるからです。入力全体を 1 つのノルムで測る条件数と、成分ごとに測る条件数の 2 通りを、次の定義で並べて定めます。どちらも「入力を小さくずらしたとき、出力の相対的な変化が入力の相対的な変化の何倍か」の最悪値(sup⁡\sup)を、ずらしを 0 に近づけた極限で見ています。

定義 2.1(相対条件数)↗

U⊂RnU\subset\mathbb{R}^n を開集合、f:U→Rmf:U\to\mathbb{R}^m、x∈U\boldsymbol{x}\in U で x≠0\boldsymbol{x}\ne\boldsymbol{0}, f(x)≠0f(\boldsymbol{x})\ne\boldsymbol{0} とする。

  1. (ノルムによる)相対条件数を κ(x)=lim⁡ε→+0 sup⁡{∥f(x+Δx)−f(x)∥/∥f(x)∥∥Δx∥/∥x∥:0<∥Δx∥≤ε∥x∥}\kappa(\boldsymbol{x})=\lim_{\varepsilon\to+0}\ \sup\left\{\frac{\|f(\boldsymbol{x}+\Delta\boldsymbol{x})-f(\boldsymbol{x})\|/\|f(\boldsymbol{x})\|}{\|\Delta\boldsymbol{x}\|/\|\boldsymbol{x}\|}:0\lt\|\Delta\boldsymbol{x}\|\le\varepsilon\|\boldsymbol{x}\|\right\} と定める。
  2. m=1m=1 のとき、成分ごとの相対条件数を κc(x)=lim⁡ε→+0 sup⁡{∣f(x+Δx)−f(x)∣∣f(x)∣ ηx(Δx):0<ηx(Δx)≤ε}\kappa_{\mathrm{c}}(\boldsymbol{x})=\lim_{\varepsilon\to+0}\ \sup\left\{\frac{|f(\boldsymbol{x}+\Delta\boldsymbol{x})-f(\boldsymbol{x})|}{|f(\boldsymbol{x})|\,\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})}:0\lt\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})\le\varepsilon\right\} と定める。

(ε\varepsilon を小さくすると sup⁡\sup をとる集合が小さくなるので、sup⁡\sup は ε\varepsilon について単調非減少で、極限は [0,∞][0,\infty] に存在する。Δx\Delta\boldsymbol{x} は x+Δx∈U\boldsymbol{x}+\Delta\boldsymbol{x}\in U の範囲を動く。)

条件数は「入力の相対誤差を何倍に拡大して出力の相対誤差にするか」の、摂動が小さい極限での最悪値です。κ≈10k\kappa\approx10^k なら、入力に相対 uu の誤差があるだけで、出力は kk 桁ほど失われうる、と読みます。浮動小数点数の入力は最初から相対 uu の誤差をもちうるので、成分ごとの条件数は計算機の上の問題の感度を直接表します。

定義の sup⁡\sup と極限は、そのままでは計算できません。次の命題は、ff が微分できれば条件数が微分(ヤコビ行列)の大きさで書けることを示します。証明では、ff を一次近似 JhJ\boldsymbol{h} と残り r(h)r(\boldsymbol{h}) に分け、残りが十分小さいことを使って、条件数を上と下の両側から ∥J∥∥x∥/∥f(x)∥\|J\|\|\boldsymbol{x}\|/\|f(\boldsymbol{x})\| ではさみます。

命題 2.2(微分可能な問題の条件数)✓

定義 2.1 の状況で、ff が x\boldsymbol{x} で全微分可能(定義 9.1[多変数関数の微分と偏微分])で、そのヤコビ行列を J=Jf(x)J=J_f(\boldsymbol{x}) とする。

  1. κ(x)=∥J∥ ∥x∥∥f(x)∥\kappa(\boldsymbol{x})=\dfrac{\|J\|\,\|\boldsymbol{x}\|}{\|f(\boldsymbol{x})\|}。とくに n=m=1n=m=1 なら κ(x)=∣xf′(x)f(x)∣\kappa(x)=\left|\dfrac{xf'(x)}{f(x)}\right|。
  2. m=1m=1 なら κc(x)=1∣f(x)∣∑i=1n∣xi∣∣∂f∂xi(x)∣\kappa_{\mathrm{c}}(\boldsymbol{x})=\dfrac{1}{|f(\boldsymbol{x})|}\displaystyle\sum_{i=1}^n|x_i|\left|\frac{\partial f}{\partial x_i}(\boldsymbol{x})\right|。
証明(命題 2.2)

r(h)=f(x+h)−f(x)−Jhr(\boldsymbol{h})=f(\boldsymbol{x}+\boldsymbol{h})-f(\boldsymbol{x})-J\boldsymbol{h} とおくと、全微分可能性から ∥r(h)∥/∥h∥→0\|r(\boldsymbol{h})\|/\|\boldsymbol{h}\|\to0(h→0\boldsymbol{h}\to\boldsymbol{0})です。ρ(ε)=sup⁡{∥r(h)∥/∥h∥:0<∥h∥≤ε∥x∥}\rho(\varepsilon)=\sup\{\|r(\boldsymbol{h})\|/\|\boldsymbol{h}\|:0\lt\|\boldsymbol{h}\|\le\varepsilon\|\boldsymbol{x}\|\} とおくと ρ(ε)→0\rho(\varepsilon)\to0(ε→+0\varepsilon\to+0)です。

  1. 上からの評価. 0<∥h∥≤ε∥x∥0\lt\|\boldsymbol{h}\|\le\varepsilon\|\boldsymbol{x}\| なら、三角不等式と作用素ノルムの定義から ∥f(x+h)−f(x)∥≤(∥J∥+ρ(ε))∥h∥\|f(\boldsymbol{x}+\boldsymbol{h})-f(\boldsymbol{x})\|\le(\|J\|+\rho(\varepsilon))\|\boldsymbol{h}\| なので、定義の sup⁡\sup は (∥J∥+ρ(ε))∥x∥/∥f(x)∥(\|J\|+\rho(\varepsilon))\|\boldsymbol{x}\|/\|f(\boldsymbol{x})\| 以下です。ε→+0\varepsilon\to+0 として κ(x)≤∥J∥∥x∥/∥f(x)∥\kappa(\boldsymbol{x})\le\|J\|\|\boldsymbol{x}\|/\|f(\boldsymbol{x})\|。

    下からの評価. τ>0\tau\gt0 を任意にとり、∥v∥=1\|\boldsymbol{v}\|=1, ∥Jv∥≥∥J∥−τ\|J\boldsymbol{v}\|\ge\|J\|-\tau となる v\boldsymbol{v} を選びます(作用素ノルムは上限なので選べます)。h=ε∥x∥v\boldsymbol{h}=\varepsilon\|\boldsymbol{x}\|\boldsymbol{v} とすると ∥f(x+h)−f(x)∥≥∥Jh∥−∥r(h)∥≥(∥J∥−τ−ρ(ε))∥h∥\|f(\boldsymbol{x}+\boldsymbol{h})-f(\boldsymbol{x})\|\ge\|J\boldsymbol{h}\|-\|r(\boldsymbol{h})\|\ge(\|J\|-\tau-\rho(\varepsilon))\|\boldsymbol{h}\| なので、sup⁡\sup は (∥J∥−τ−ρ(ε))∥x∥/∥f(x)∥(\|J\|-\tau-\rho(\varepsilon))\|\boldsymbol{x}\|/\|f(\boldsymbol{x})\| 以上です。ε→+0\varepsilon\to+0, τ→+0\tau\to+0 として逆向きの不等式を得ます。1 変数では ∥J∥=∣f′(x)∣\|J\|=|f'(x)| です。

  2. g=(∂1f(x),…,∂nf(x))\boldsymbol{g}=(\partial_1f(\boldsymbol{x}),\ldots,\partial_nf(\boldsymbol{x})) とすると Jh=g⋅hJ\boldsymbol{h}=\boldsymbol{g}\cdot\boldsymbol{h} です。S=∑i∣xi∣∣gi∣S=\sum_i|x_i||g_i| とおきます。0<ηx(Δx)=η≤ε0\lt\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})=\eta\le\varepsilon なら ∥Δx∥≤η∥x∥\|\Delta\boldsymbol{x}\|\le\eta\|\boldsymbol{x}\| なので

    ∣f(x+Δx)−f(x)∣≤∑i∣gi∣∣Δxi∣+∣r(Δx)∣≤ηS+η∥x∥ρ(ε)|f(\boldsymbol{x}+\Delta\boldsymbol{x})-f(\boldsymbol{x})|\le\sum_i|g_i||\Delta x_i|+|r(\Delta\boldsymbol{x})|\le\eta S+\eta\|\boldsymbol{x}\|\rho(\varepsilon)

    で、sup⁡\sup は (S+∥x∥ρ(ε))/∣f(x)∣(S+\|\boldsymbol{x}\|\rho(\varepsilon))/|f(\boldsymbol{x})| 以下です。逆に、gi≠0g_i\ne0 の成分は Δxi=η∣xi∣sign⁡(gi)\Delta x_i=\eta|x_i|\operatorname{sign}(g_i)、gi=0g_i=0 の成分は Δxi=ηxi\Delta x_i=\eta x_i とおくと、x≠0\boldsymbol{x}\ne\boldsymbol{0} から ηx(Δx)=η\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})=\eta で、g⋅Δx=ηS\boldsymbol{g}\cdot\Delta\boldsymbol{x}=\eta S です。よって ∣f(x+Δx)−f(x)∣≥ηS−η∥x∥ρ(ε)|f(\boldsymbol{x}+\Delta\boldsymbol{x})-f(\boldsymbol{x})|\ge\eta S-\eta\|\boldsymbol{x}\|\rho(\varepsilon) で、η=ε→+0\eta=\varepsilon\to+0 とすれば κc(x)≥S/∣f(x)∣\kappa_{\mathrm{c}}(\boldsymbol{x})\ge S/|f(\boldsymbol{x})| です。

例 2.3(基本的な関数の条件数)

命題 2.2 から、次の表が得られます(x,x1,x2x,x_1,x_2 は条件数の分母が 00 にならない範囲)。

問題条件数読み方
x1+x2x_1+x_2κc=∣x1∣+∣x2∣∣x1+x2∣\kappa_{\mathrm{c}}=\dfrac{\vert x_1\vert +\vert x_2\vert }{\vert x_1+x_2\vert }同符号なら 11、打ち消し合うと大きい(桁落ち)
x1x2x_1x_2, x1/x2x_1/x_2κc=2\kappa_{\mathrm{c}}=2つねに条件がよい
x\sqrt{x}κ=1/2\kappa=1/2誤差を半分にする
exe^xκ=∣x∣\kappa=\vert x\vert ∣x∣\vert x\vert が大きいと悪い
log⁡x\log xκ=1/∣log⁡x∣\kappa=1/\vert \log x\vert x≈1x\approx1 で悪い
log⁡(1+x)\log(1+x)(xx を入力とみる)κ=∣x∣(1+x)∣log⁡(1+x)∣\kappa=\dfrac{\vert x\vert }{(1+x)\vert \log(1+x)\vert }x→0x\to0 で 11 に近づく

最後の 2 行は、同じ値 log⁡(1+x)\log(1+x) でも「何を入力とみるか」で条件数が違うことを示しています。y=1+xy=1+x を入力とすると κ=1/∣log⁡y∣≈1/∣x∣\kappa=1/|\log y|\approx1/|x| ですが、xx そのものを入力とすると κ≈1\kappa\approx1 です。xx が与えられているのに 1+x1+x を先に計算すると、条件の悪い問題を自分で作ってしまいます(6 節)。

命題 3.1(単根の摂動)✓

pp, qq を実係数の多項式とし、x∗x^\ast を pp の単根(p(x∗)=0p(x^\ast)=0, p′(x∗)≠0p'(x^\ast)\ne0)とする。このとき δ>0\delta\gt0 と x∗x^\ast の開近傍 VV、C1C^1 級の関数 x:(−δ,δ)→Vx:(-\delta,\delta)\to V があって、∣ε∣<δ|\varepsilon|\lt\delta のとき p+εqp+\varepsilon q の VV の中の根は x(ε)x(\varepsilon) だけであり、

x(0)=x∗,x′(0)=−q(x∗)p′(x∗)x(0)=x^\ast,\qquad x'(0)=-\frac{q(x^\ast)}{p'(x^\ast)}

が成り立つ。

証明(命題 3.1)

F(ε,x)=p(x)+εq(x)F(\varepsilon,x)=p(x)+\varepsilon q(x) は R2\mathbb{R}^2 上の多項式なので C1C^1 級で、F(0,x∗)=0F(0,x^\ast)=0, ∂F/∂x(0,x∗)=p′(x∗)≠0\partial F/\partial x(0,x^\ast)=p'(x^\ast)\ne0 です。陰関数定理(定理 5.1[逆関数定理・陰関数定理と条件付き極値])を n=m=1n=m=1 で使うと、00 の開近傍 XX と x∗x^\ast の開近傍 VV、C1C^1 級の g:X→Vg:X\to V があって、X×VX\times V の中の F=0F=0 の点はちょうど (ε,g(ε))(\varepsilon,g(\varepsilon)) で、g(0)=x∗g(0)=x^\ast です。X⊃(−δ,δ)X\supset(-\delta,\delta) となる δ\delta をとり x=gx=g とします。同じ定理の導関数の公式から

x′(0)=−(∂F∂x(0,x∗))−1∂F∂ε(0,x∗)=−q(x∗)p′(x∗)x'(0)=-\left(\frac{\partial F}{\partial x}(0,x^\ast)\right)^{-1}\frac{\partial F}{\partial\varepsilon}(0,x^\ast)=-\frac{q(x^\ast)}{p'(x^\ast)}

です。

係数 aja_j だけを相対 ε\varepsilon だけ動かすのは q(x)=ajxjq(x)=a_jx^j の場合で、根の相対変化は 1 次で ε ∣aj(x∗)j−1/p′(x∗)∣\varepsilon\,|a_j(x^\ast)^{j-1}/p'(x^\ast)| です。すべての係数を相対 ε\varepsilon 以内で動かすと(q=∑jθjajxjq=\sum_j\theta_ja_jx^j, ∣θj∣≤1|\theta_j|\le1)、根の変化は 1 次で ε∑j∣aj∣∣x∗∣j/∣p′(x∗)∣\varepsilon\sum_j|a_j||x^\ast|^j/|p'(x^\ast)| 以下で、この上限は θj\theta_j の符号を選べば達成されます。

例 3.2(Wilkinson の多項式)

w(x)=∏k=120(x−k)=x20−210x19+⋯+20!w(x)=\prod_{k=1}^{20}(x-k)=x^{20}-210x^{19}+\cdots+20! の根は 1,…,201,\ldots,20 で、互いに 1 ずつ離れた「よく分かれた」根です。x19x^{19} の係数を −210−2−23-210-2^{-23} に変える(q(x)=−x19q(x)=-x^{19}, ε=2−23\varepsilon=2^{-23})と、命題 3.1 から根 kk は 1 次で εk19/w′(k)\varepsilon k^{19}/w'(k) 動きます。w′(k)=∏j≠k(k−j)=(−1)20−k(k−1)! (20−k)!w'(k)=\prod_{j\ne k}(k-j)=(-1)^{20-k}(k-1)!\,(20-k)! です。

次のコードは、(i) 1 次の予測 εk19/w′(k)\varepsilon k^{19}/w'(k)、(ii) 摂動を 10−1210^{-12} 倍に小さくしたときの実際の変化と 1 次の予測の比(mpmath の 50 桁で根を求める)、(iii) 係数を binary64 に丸めて np.roots で解いた根の誤差、(iv) すべての係数に相対 uu の誤差があるときの 1 次の評価 u∑j∣aj∣kj/∣w′(k)∣u\sum_j|a_j|k^j/|w'(k)| を並べます。最後の行は ε=2−23\varepsilon=2^{-23} そのもので摂動したときの結果です。

# Python 3.12.10 / NumPy 2.5.2 / mpmath 1.3.0(x86-64)
from math import factorial as fac
import numpy as np
import mpmath as mp
mp.mp.dps = 50
c = [1] # prod (x - k) の係数(整数, 降べき)
for k in range(1, 21):
c = [a - k * b for a, b in zip(c + [0], [0] + c)]
def roots(e): # x^19 の係数から e を引いた根
cp = [mp.mpf(a) for a in c]
cp[1] -= e
return mp.polyroots(cp, maxsteps=300, extraprec=300)
e0 = mp.mpf(2) ** -23
small = roots(e0 * mp.mpf(10) ** -12)
big = roots(e0)
rn = np.roots(np.array(c, dtype=float)) # 係数を binary64 に丸めて解く
u = 2.0 ** -53
for k in (1, 4, 8, 12, 16, 20):
dp = (-1) ** (20 - k) * fac(k - 1) * fac(20 - k) # p'(k)
pred = e0 * mp.mpf(k) ** 19 / dp # 1 次の予測 e k^19/p'(k)
z = min(small, key=lambda z: abs(z - k)) - k
ratio = mp.re(z) / (pred * mp.mpf(10) ** -12)
cnd = sum(abs(a) * k ** (20 - i) for i, a in enumerate(c)) / abs(dp)
err = np.min(np.abs(rn - k))
print(f"{k:>2} {float(pred):9.2e} {float(ratio):.4f}"
f" {err:.2e} {u * cnd:.2e}")
nonreal = [z for z in big if abs(mp.im(z)) > 1e-30]
print("2^-23 で実でない根", len(nonreal),
"虚部の最大", mp.nstr(max(abs(mp.im(z)) for z in big), 3))
1 -9.80e-25 1.0000 1.92e-13 4.66e-14
4 2.61e-10 1.0000 1.62e-08 2.29e-08
8 7.12e-03 1.0000 7.21e-04 3.48e-04
12 2.37e+01 1.0000 5.17e-02 3.79e-02
16 2.87e+02 1.0000 5.76e-02 6.29e-02
20 5.14e+00 1.0000 1.96e-04 3.06e-04
2^-23 で実でない根 10 虚部の最大 2.81

検算. (a) 既知値: 摂動前の根は整数 kk で、ε=2−23\varepsilon=2^{-23} のとき 10 個の根が 5 組の共役複素数になり、虚部が最大の組は 16.7307±2.8126i16.7307\pm2.8126i です(Wilkinson が報告した値と一致します)。(b) 別精度・別手法: 50 桁の mpmath と、係数を binary64 に丸めた np.roots の誤差は、係数の丸めだけから予測される (iv) と同じ桁で、比は 0.6〜4 倍の範囲です(np.roots 自身の丸め誤差が加わるため完全には一致しません)。(c) 次数: 摂動を 10−1210^{-12} 倍にすると、実際の変化と 1 次の予測の比はどの根でも 1.00001.0000 で、変化が摂動に比例する(1 次の項が支配する)ことがわかります。一方 ε=2−23\varepsilon=2^{-23} では予測される変化が k=16k=16 で 287287 と根の間隔 11 を大きく超え、1 次の近似は成り立たず、根は複素数に移ります。

Wilkinson の多項式は、根がよく分かれていても、係数で表した多項式の根は極端に条件が悪くなりうることを示しています。根 1616 の (iv) の評価は 6.3×10−26.3\times10^{-2} で、係数を倍精度で持つだけで小数第 2 位が怪しくなります。固有値を特性多項式の根として計算しないのはこのためです(数値線形代数のテーマで、行列のまま固有値を計算する方法を扱います)。

問題 ff を解くアルゴリズムが、入力 x\boldsymbol{x} に対して計算値 y^\hat{\boldsymbol{y}} を返したとします。

後退誤差の考え方は、「計算値 y^\hat{\boldsymbol{y}} が、入力を少しだけずらした問題の正確な答えになっていれば、そのずらし幅がアルゴリズムの誤差だ」というものです。次の定義の inf⁡\inf は、そのようなずらし方のうち最小のものを選ぶ、という意味です。

定義 4.1(前進誤差と後退誤差)↗

定義 2.1 の状況で、計算値 y^∈Rm\hat{\boldsymbol{y}}\in\mathbb{R}^m について、

  1. (相対)前進誤差を ∥y^−f(x)∥/∥f(x)∥\|\hat{\boldsymbol{y}}-f(\boldsymbol{x})\|/\|f(\boldsymbol{x})\| と定める。
  2. (ノルムによる相対)後退誤差を η(y^)=inf⁡{∥Δx∥∥x∥:x+Δx∈U, f(x+Δx)=y^}\eta(\hat{\boldsymbol{y}})=\inf\left\{\frac{\|\Delta\boldsymbol{x}\|}{\|\boldsymbol{x}\|}:\boldsymbol{x}+\Delta\boldsymbol{x}\in U,\ f(\boldsymbol{x}+\Delta\boldsymbol{x})=\hat{\boldsymbol{y}}\right\} と定める(集合が空なら ∞\infty)。∥Δx∥/∥x∥\|\Delta\boldsymbol{x}\|/\|\boldsymbol{x}\| の代わりに ηx(Δx)\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x}) を使ったものを成分ごとの後退誤差 ηc(y^)\eta_{\mathrm{c}}(\hat{\boldsymbol{y}}) という。

前進誤差は「答えがどれだけ違うか」、後退誤差は「どれだけ違う問題の正確な答えか」です。後者は、真の答え f(x)f(\boldsymbol{x}) を知らなくても、y^\hat{\boldsymbol{y}} を代入して確かめられることがあります(線形方程式の残差など)。

定義 4.2(後退安定と混合安定)↗

問題 ff の定義域の部分集合 DD の入力に対し、単位丸め uu の浮動小数点演算で計算値 f^(x)\hat f(\boldsymbol{x}) を返すアルゴリズムを考える。x\boldsymbol{x} と uu によらない定数 CC(入力の次元 nn などには依ってよい)があって、

  1. すべての x∈D\boldsymbol{x}\in D で後退誤差(ノルムによる、または成分ごと)が CuCu 以下のとき、アルゴリズムは(その意味で)後退安定であるという。
  2. すべての x∈D\boldsymbol{x}\in D で f^(x)+Δy=f(x+Δx)\hat f(\boldsymbol{x})+\Delta\boldsymbol{y}=f(\boldsymbol{x}+\Delta\boldsymbol{x}), ∥Δy∥≤Cu∥f^(x)∥\|\Delta\boldsymbol{y}\|\le Cu\|\hat f(\boldsymbol{x})\|, ∥Δx∥≤Cu∥x∥\|\Delta\boldsymbol{x}\|\le Cu\|\boldsymbol{x}\| となる Δx\Delta\boldsymbol{x}, Δy\Delta\boldsymbol{y} があるとき、混合安定(前進後退安定)であるという。

後退安定なら混合安定です(Δy=0\Delta\boldsymbol{y}=\boldsymbol{0})。混合安定は「少しずらした入力の正確な答えに近い」ことで、多くのアルゴリズムで期待できる最良の性質です。

入力出力xx + Δxf(x)ŷ = f(x + Δx)f(正確な計算)アルゴリズム後退誤差前進誤差
前進誤差と後退誤差。計算値 ŷ を、ずらした入力 x + Δx の正確な答えとみなす。答えのずれ(前進誤差)は、入力のずれ(後退誤差)を条件数倍したもので抑えられる。

4.2. 前進誤差 ≲ 条件数 × 後退誤差

Section titled “4.2. 前進誤差 ≲ 条件数 × 後退誤差”

定理 4.3(前進誤差と後退誤差の関係)✓

U⊂RnU\subset\mathbb{R}^n を開集合、f:U→Rmf:U\to\mathbb{R}^m、x∈U\boldsymbol{x}\in U, x≠0\boldsymbol{x}\ne\boldsymbol{0}, f(x)≠0f(\boldsymbol{x})\ne\boldsymbol{0} とし、y^=f(x+Δx)\hat{\boldsymbol{y}}=f(\boldsymbol{x}+\Delta\boldsymbol{x})(x+Δx∈U\boldsymbol{x}+\Delta\boldsymbol{x}\in U)とする。

  1. (1 次の評価) ff が x\boldsymbol{x} で全微分可能なら ∥y^−f(x)∥∥f(x)∥≤κ(x)∥Δx∥∥x∥+R(Δx),lim⁡Δx→0R(Δx)∥Δx∥=0\frac{\|\hat{\boldsymbol{y}}-f(\boldsymbol{x})\|}{\|f(\boldsymbol{x})\|}\le\kappa(\boldsymbol{x})\frac{\|\Delta\boldsymbol{x}\|}{\|\boldsymbol{x}\|}+R(\Delta\boldsymbol{x}),\qquad\lim_{\Delta\boldsymbol{x}\to\boldsymbol{0}}\frac{R(\Delta\boldsymbol{x})}{\|\Delta\boldsymbol{x}\|}=0 を満たす R≥0R\ge0(x\boldsymbol{x} と ff だけで決まり、Δx≠0\Delta\boldsymbol{x}\ne\boldsymbol{0} で定義される)がある。これを o(∥Δx∥)o(\|\Delta\boldsymbol{x}\|) の項と呼ぶ。
  2. (非漸近の評価) 線分 L={x+tΔx:0≤t≤1}L=\{\boldsymbol{x}+t\Delta\boldsymbol{x}:0\le t\le1\} が UU に含まれ、ff が LL の各点で全微分可能なら ∥y^−f(x)∥∥f(x)∥≤(sup⁡z∈L∥Jf(z)∥ ∥x∥∥f(x)∥)∥Δx∥∥x∥.\frac{\|\hat{\boldsymbol{y}}-f(\boldsymbol{x})\|}{\|f(\boldsymbol{x})\|}\le\left(\sup_{\boldsymbol{z}\in L}\frac{\|J_f(\boldsymbol{z})\|\,\|\boldsymbol{x}\|}{\|f(\boldsymbol{x})\|}\right)\frac{\|\Delta\boldsymbol{x}\|}{\|\boldsymbol{x}\|}.
  3. (成分ごと) m=1m=1 で、2 と同じ仮定のもとで ∣y^−f(x)∣∣f(x)∣≤(sup⁡z∈L1∣f(x)∣∑i=1n∣xi∣∣∂f∂xi(z)∣)ηx(Δx).\frac{|\hat y-f(\boldsymbol{x})|}{|f(\boldsymbol{x})|}\le\left(\sup_{\boldsymbol{z}\in L}\frac{1}{|f(\boldsymbol{x})|}\sum_{i=1}^n|x_i|\left|\frac{\partial f}{\partial x_i}(\boldsymbol{z})\right|\right)\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x}).
証明(定理 4.3)
  1. r(h)=f(x+h)−f(x)−Jf(x)hr(\boldsymbol{h})=f(\boldsymbol{x}+\boldsymbol{h})-f(\boldsymbol{x})-J_f(\boldsymbol{x})\boldsymbol{h} とすると、全微分可能性(定義 9.1[多変数関数の微分と偏微分])から ∥r(Δx)∥/∥Δx∥→0\|r(\Delta\boldsymbol{x})\|/\|\Delta\boldsymbol{x}\|\to0(Δx→0\Delta\boldsymbol{x}\to\boldsymbol{0})です。三角不等式から ∥y^−f(x)∥≤∥Jf(x)∥∥Δx∥+∥r(Δx)∥\|\hat{\boldsymbol{y}}-f(\boldsymbol{x})\|\le\|J_f(\boldsymbol{x})\|\|\Delta\boldsymbol{x}\|+\|r(\Delta\boldsymbol{x})\| で、両辺を ∥f(x)∥\|f(\boldsymbol{x})\| で割り、命題 2.2 の 1 の κ(x)=∥Jf(x)∥∥x∥/∥f(x)∥\kappa(\boldsymbol{x})=\|J_f(\boldsymbol{x})\|\|\boldsymbol{x}\|/\|f(\boldsymbol{x})\| を使えば、R(Δx)=∥r(Δx)∥/∥f(x)∥R(\Delta\boldsymbol{x})=\|r(\Delta\boldsymbol{x})\|/\|f(\boldsymbol{x})\| として主張です(∥f(x)∥\|f(\boldsymbol{x})\| は定数なので R(Δx)/∥Δx∥→0R(\Delta\boldsymbol{x})/\|\Delta\boldsymbol{x}\|\to0)。
  2. 平均値不等式(定理 9.7[多変数関数の微分と偏微分])から、ある θ∈(0,1)\theta\in(0,1) で ∥f(x+Δx)−f(x)∥≤∥Jf(x+θΔx)∥∥Δx∥\|f(\boldsymbol{x}+\Delta\boldsymbol{x})-f(\boldsymbol{x})\|\le\|J_f(\boldsymbol{x}+\theta\Delta\boldsymbol{x})\|\|\Delta\boldsymbol{x}\| です。右辺の ∥Jf∥\|J_f\| を LL 上の上限で置き換え、∥f(x)∥\|f(\boldsymbol{x})\| で割って ∥x∥\|\boldsymbol{x}\| を掛け・割りすれば主張です。
  3. η=ηx(Δx)\eta=\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x}) とし、φ(t)=f(x+tΔx)\varphi(t)=f(\boldsymbol{x}+t\Delta\boldsymbol{x}) とおきます。UU は開集合なので {t:x+tΔx∈U}\{t:\boldsymbol{x}+t\Delta\boldsymbol{x}\in U\} は [0,1][0,1] を含む開集合で、連鎖律(定理 9.4[多変数関数の微分と偏微分])から φ\varphi は [0,1][0,1] の各点で微分可能、φ′(t)=∑i∂if(x+tΔx)Δxi\varphi'(t)=\sum_i\partial_if(\boldsymbol{x}+t\Delta\boldsymbol{x})\Delta x_i です。平均値の定理(定理 3.3[平均値の定理とテイラーの定理])から、ある ξ∈(0,1)\xi\in(0,1) で ∣y^−f(x)∣=∣φ(1)−φ(0)∣=∣φ′(ξ)∣≤∑i∣∂if(z)∣∣Δxi∣≤η∑i∣xi∣∣∂if(z)∣|\hat y-f(\boldsymbol{x})|=|\varphi(1)-\varphi(0)|=|\varphi'(\xi)|\le\sum_i|\partial_if(\boldsymbol{z})||\Delta x_i|\le\eta\sum_i|x_i||\partial_if(\boldsymbol{z})| (z=x+ξΔx∈L\boldsymbol{z}=\boldsymbol{x}+\xi\Delta\boldsymbol{x}\in L)です。上限で置き換えて ∣f(x)∣|f(\boldsymbol{x})| で割れば主張です。

1 は「前進誤差 ≈ 条件数 × 後退誤差」の正確な意味です。2 と 3 は o(⋅)o(\cdot) の項を含まない評価で、誤差の上界を保証したいとき(計算機援用証明など)に使えます。とくに ff が入力について 1 次(線形)なら、2・3 の上限は x\boldsymbol{x} での値と等しく、評価は κ×\kappa\times 後退誤差そのものになります。

この定理を後退安定なアルゴリズムに当てはめると、後退安定なアルゴリズムの前進誤差は、およそ κ⋅Cu\kappa\cdot Cu 以下です。したがって、

  • κ\kappa が小さい問題を後退安定なアルゴリズムで解けば、答えは正確です。
  • κu≳1\kappa u\gtrsim1 の問題は、どんなアルゴリズムでも(入力の丸めだけで)答えが保証されません。精度を上げるか、問題の定式化を変えます。
  • 前進誤差が κu\kappa u より桁違いに大きいなら、そのアルゴリズムは後退安定ではありません(6 節の分散の 1 パス公式)。

命題 5.1(四則・内積・Horner 法の後退安定性)✓

オーバーフローとアンダーフローは起きないとする。

  1. x,y∈Fx,y\in\mathbb{F} について、fl(x±y)=x(1+δ)±y(1+δ)\mathrm{fl}(x\pm y)=x(1+\delta)\pm y(1+\delta), fl(xy)=x(1+δ) y\mathrm{fl}(xy)=x(1+\delta)\,y, fl(x/y)=x(1+δ)/y\mathrm{fl}(x/y)=x(1+\delta)/y(∣δ∣≤u|\delta|\le u)。したがって四則は成分ごとの後退誤差 uu 以下で後退安定である。
  2. x,y∈Fn\boldsymbol{x},\boldsymbol{y}\in\mathbb{F}^n、nu<1nu\lt1 とし、内積を前から順に計算した値を s^\hat s とする。s^=(x+Δx)Ty\hat s=(\boldsymbol{x}+\Delta\boldsymbol{x})^{\mathsf{T}}\boldsymbol{y}, ∣Δx∣≤γn∣x∣|\Delta\boldsymbol{x}|\le\gamma_n|\boldsymbol{x}|(成分ごと)となる Δx\Delta\boldsymbol{x} がある。すなわち内積は x\boldsymbol{x} について成分ごとの後退誤差 γn\gamma_n 以下である。
  3. Horner 法で計算した ∑i=0naixi\sum_{i=0}^na_ix^i の値は、係数 (a0,…,an)(a_0,\ldots,a_n) について成分ごとの後退誤差 γ2n\gamma_{2n} 以下である(2nu<12nu\lt1)。
証明(命題 5.1)
  1. 標準モデル(系 3.1[浮動小数点数と丸め誤差])から fl(x∘y)=(x∘y)(1+δ)\mathrm{fl}(x\circ y)=(x\circ y)(1+\delta), ∣δ∣≤u|\delta|\le u で、右辺を書き直したものです。
  2. 内積の丸め誤差の定理(定理 3.3[浮動小数と区間演算])から s^=∑ixiyi(1+θ(i))\hat s=\sum_ix_iy_i(1+\theta^{(i)}), ∣θ(i)∣≤γn|\theta^{(i)}|\le\gamma_n なので、Δxi=xiθ(i)\Delta x_i=x_i\theta^{(i)} とおけばよいです。
  3. Horner 法の後退誤差(定理 6.1[浮動小数点数と丸め誤差])そのものです。

命題 5.2(多項式の値の条件数と Horner 法の前進誤差)✓

p(x)=∑i=0naixip(x)=\sum_{i=0}^na_ix^i の値を係数 a=(a0,…,an)\boldsymbol{a}=(a_0,\ldots,a_n) の関数とみたとき、p(x)≠0p(x)\ne0 ならその成分ごとの条件数は

κp(x)=∑i=0n∣ai∣∣x∣i∣p(x)∣\kappa_p(x)=\frac{\sum_{i=0}^n|a_i||x|^i}{|p(x)|}

であり、x,ai∈Fx,a_i\in\mathbb{F}, 2nu<12nu\lt1 で Horner 法の途中でオーバーフローもアンダーフローも起きなければ、計算値 p^\hat p は

∣p^−p(x)∣∣p(x)∣≤γ2n κp(x)\frac{|\hat p-p(x)|}{|p(x)|}\le\gamma_{2n}\,\kappa_p(x)

を満たす。

証明(命題 5.2)

a↦∑iaixi\boldsymbol{a}\mapsto\sum_ia_ix^i は 1 次式で ∂/∂ai=xi\partial/\partial a_i=x^i なので、命題 2.2 の 2 から κp(x)\kappa_p(x) は上の形です。定理 6.1[浮動小数点数と丸め誤差] から p^=∑iai(1+θi)xi\hat p=\sum_ia_i(1+\theta_i)x^i, ∣θi∣≤γ2n|\theta_i|\le\gamma_{2n} なので、∣p^−p(x)∣=∣∑iaiθixi∣≤γ2n∑i∣ai∣∣x∣i|\hat p-p(x)|=|\sum_ia_i\theta_ix^i|\le\gamma_{2n}\sum_i|a_i||x|^i で、∣p(x)∣|p(x)| で割れば主張です(定理 4.3 の 3 を 1 次式に使ったものと同じです)。

浮動小数点数と丸め誤差の演習で扱った (x−1)10(x-1)^{10} の展開は κp(1.01)≈1023\kappa_p(1.01)\approx10^{23} で、γ20κp≫1\gamma_{20}\kappa_p\gg1 でした。Horner 法は後退安定でも、問題(展開した係数から値を求めること)の条件が悪すぎたわけです。

例 5.3(外積の計算は後退安定でない)

x,y∈Fn\boldsymbol{x},\boldsymbol{y}\in\mathbb{F}^n の外積 A=xyTA=\boldsymbol{x}\boldsymbol{y}^{\mathsf{T}} を a^ij=fl(xiyj)=xiyj(1+δij)\hat a_{ij}=\mathrm{fl}(x_iy_j)=x_iy_j(1+\delta_{ij}) で計算すると、各成分の相対誤差は uu 以下で、前進誤差は小さく混合安定です。しかし後退安定ではありません。もし A^=(x+Δx)(y+Δy)T\hat A=(\boldsymbol{x}+\Delta\boldsymbol{x})(\boldsymbol{y}+\Delta\boldsymbol{y})^{\mathsf{T}} と書けるなら A^\hat A の階数は 1 以下ですが、δij\delta_{ij} はそろわないので、A^\hat A は一般に階数 2 以上になるからです。たとえば binary64 で x=(1,fl(1/3))\boldsymbol{x}=(1,\mathrm{fl}(1/3)), y=(fl(0.1),fl(0.7))\boldsymbol{y}=(\mathrm{fl}(0.1),\mathrm{fl}(0.7)) とすると、第 1 行は厳密で、第 2 行の 2 成分の相対誤差は −1.4×10−17-1.4\times10^{-17} と 1.6×10−171.6\times10^{-17} と異なり、有理数で計算した det⁡A^\det\hat A は約 6.9×10−19≠06.9\times10^{-19}\ne0 です。後退安定性は「出力が入力の集合の像に入るか」という性質なので、出力の次元が入力より大きい問題では成り立たないことがよくあります。

6. 条件のよい問題を安定に解く書き換え

Section titled “6. 条件のよい問題を安定に解く書き換え”

ここでは、問題の条件数は小さいのに、素朴な式が不安定なアルゴリズムになっている例を 3 つ見ます。どれも、桁落ち(命題 4.2[浮動小数点数と丸め誤差])が丸め誤差を拡大しています。

例 6.1(2 次方程式の解の公式)

x2+bx+c=0x^2+bx+c=0(b2>4cb^2\gt4c, c≠0c\ne0)の解を x±=(−b±b2−4c)/2x_\pm=(-b\pm\sqrt{b^2-4c})/2 で計算します。b2≫4∣c∣b^2\gg4|c| だと b2−4c≈∣b∣\sqrt{b^2-4c}\approx|b| なので、−b-b と同じ符号の平方根を足す方の解は問題ありませんが、他方は桁落ちを起こします。binary64 で b=108b=10^8, c=1c=1 とすると、小さい方の解の真値は約 −1.0×10−8-1.0\times10^{-8} ですが、(−b+b2−4c)/2(-b+\sqrt{b^2-4c})/2 は −7.45×10−9-7.45\times10^{-9} になり、相対誤差は 0.250.25 です。

安定な計算法は、桁落ちしない方の解 x1=(−b−sign⁡(b)b2−4c)/2x_1=(-b-\operatorname{sign}(b)\sqrt{b^2-4c})/2 を先に求め、もう一方を解と係数の関係 x1x2=cx_1x_2=c から x2=c/x1x_2=c/x_1 とするものです。x2x_2 の計算は掛け算と割り算だけで、相対誤差は数 uu に収まります(上の例で 7.9×10−177.9\times10^{-17})。一方、根そのものの条件数は、cc に関して ∣∂x2/∂c∣⋅∣c/x2∣=∣c/(x2(x2−x1))∣=∣x1/(x2−x1)∣≈1|\partial x_2/\partial c|\cdot|c/x_2|=|c/(x_2(x_2-x_1))|=|x_1/(x_2-x_1)|\approx1、bb に関して ∣∂x2/∂b∣⋅∣b/x2∣=∣b/(x2−x1)∣≈1|\partial x_2/\partial b|\cdot|b/x_2|=|b/(x_2-x_1)|\approx1(∣x2∣≪∣x1∣|x_2|\ll|x_1| のとき。∂x2/∂c=−1/(x2−x1)\partial x_2/\partial c=-1/(x_2-x_1), ∂x2/∂b=−x2/(x2−x1)\partial x_2/\partial b=-x_2/(x_2-x_1))で、問題は条件がよいことがわかります。

例 6.2(log1p と expm1)

例 2.3 のとおり、xx を入力とする log⁡(1+x)\log(1+x) の条件数は x→0x\to0 で 11 に近づきます。ところが np.log(1 + x) は、まず fl(1+x)=(1+x)(1+δ)\mathrm{fl}(1+x)=(1+x)(1+\delta) を作り、条件数 ≈1/∣x∣\approx1/|x| の問題 log⁡y\log y を解いてしまうので、相対誤差は u/∣x∣u/|x| 程度になります。np.log1p(x) は xx から直接 log⁡(1+x)\log(1+x) を計算する関数です。ex−1e^x-1 と np.expm1 も同じ関係です。

# Python 3.12.10 / NumPy 2.5.2 / mpmath 1.3.0(x86-64)
import numpy as np
import mpmath as mp
mp.mp.dps = 50
for k in (1, 3, 5, 7, 9, 11, 13, 15, 17):
x = 10.0 ** -k
ref = mp.log1p(mp.mpf(x)) # x は binary64 の値
e_log = abs(np.log(1 + x) - ref) / ref
e_l1p = abs(np.log1p(x) - ref) / ref
ref2 = mp.expm1(mp.mpf(x))
e_exp = abs((np.exp(x) - 1) - ref2) / ref2
e_em1 = abs(np.expm1(x) - ref2) / ref2
print(f"1e-{k:<2} {float(e_log):.2e} {float(e_l1p):.2e}"
f" {float(e_exp):.2e} {float(e_em1):.2e}")
1e-1 7.32e-16 4.00e-18 7.75e-16 1.68e-17
1e-3 1.10e-13 3.90e-17 4.29e-14 2.60e-17
1e-5 6.55e-12 1.46e-16 9.70e-12 3.11e-17
1e-7 5.84e-10 7.36e-17 5.66e-10 2.95e-17
1e-9 8.27e-08 7.49e-17 8.22e-08 7.44e-17
1e-11 8.27e-08 8.06e-17 8.27e-08 8.06e-17
1e-13 7.99e-04 1.08e-16 7.99e-04 1.78e-17
1e-15 1.10e-01 1.06e-16 1.10e-01 1.06e-16
1e-17 1.00e+00 5.00e-18 1.00e+00 5.00e-18

列は xx、log(1+x)、log1p、exp(x)-1、expm1 の相対誤差です。

検算. (a) 既知値: log⁡(1+x)=x−x2/2+⋯\log(1+x)=x-x^2/2+\cdots なので参照値は x→0x\to0 で xx に近づきます。参照値は同じ binary64 の xx に対する mpmath の 50 桁の値です。(b) 別手法: log1p と expm1 の誤差は全行で 1.5u≈1.7×10−161.5u\approx1.7\times10^{-16} 以下(u≈1.1×10−16u\approx1.1\times10^{-16} を超えるのは x=10−5x=10^{-5} の log1p だけ)で、条件数 ≈1\approx1 と後退安定性から予想される大きさです。(c) 次数: 素朴な式の誤差は u/xu/x の程度で、xx を 10−210^{-2} 倍すると誤差はおおむね 10210^2 倍になります(10−310^{-3} から 10−710^{-7} まで)。x=10−9,10−11x=10^{-9},10^{-11} で同じ値になり、x=10−13x=10^{-13} で跳ねるのは、fl(1+x)−1\mathrm{fl}(1+x)-1 が 2u2u の整数倍にしかならず、誤差が u/xu/x の上限の中で xx の 2 進展開に応じて揺れるためです。x=10−17<ux=10^{-17}\lt u では fl(1+x)=1\mathrm{fl}(1+x)=1 で、答えは 00 になります。

例 6.3(分散の 3 つの計算法)

データ x1,…,xnx_1,\ldots,x_n の標本分散 s2=1n−1∑i(xi−xˉ)2s^2=\frac1{n-1}\sum_i(x_i-\bar x)^2 を、次の 3 通りで計算します。

  • 1 パス公式: s2=1n−1(∑xi2−1n(∑xi)2)s^2=\frac1{n-1}\bigl(\sum x_i^2-\frac1n(\sum x_i)^2\bigr)。データを 1 回読むだけで済みます。
  • 2 パス公式: 平均 xˉ\bar x を先に求め、1n−1∑(xi−xˉ)2\frac1{n-1}\sum(x_i-\bar x)^2 を計算します。
  • Welford 法: Mk=Mk−1+(xk−Mk−1)/kM_k=M_{k-1}+(x_k-M_{k-1})/k、Sk=Sk−1+(xk−Mk−1)(xk−Mk)S_k=S_{k-1}+(x_k-M_{k-1})(x_k-M_k) を更新し、s2=Sn/(n−1)s^2=S_n/(n-1) とします。1 パスで済みます。

∂s2/∂xi=2(xi−xˉ)/(n−1)\partial s^2/\partial x_i=2(x_i-\bar x)/(n-1)(∑j(xj−xˉ)=0\sum_j(x_j-\bar x)=0 を使う)なので、命題 2.2 の 2 から成分ごとの条件数は κ=2∑i∣xi∣∣xi−xˉ∣/((n−1)s2)\kappa=2\sum_i|x_i||x_i-\bar x|/((n-1)s^2) で、平均 mm が標準偏差 σ\sigma より大きいと κ≈2∣m∣⋅mean∣xi−xˉ∣/s2∼∣m∣/σ\kappa\approx2|m|\cdot\mathrm{mean}|x_i-\bar x|/s^2\sim|m|/\sigma 程度になります。1 パス公式は ∑xi2≈nm2\sum x_i^2\approx nm^2 と (∑xi)2/n(\sum x_i)^2/n の差をとるので、丸め誤差が m2/σ2m^2/\sigma^2 倍に拡大されます。κu\kappa u より桁違いに大きい誤差は、定理 4.3 により後退誤差が uu 程度では説明できず、1 パス公式は後退安定ではありません。

乱数種を固定した標準正規乱数 10410^4 個に m=103,105,107m=10^3,10^5,10^7 を足したデータ(binary64)について、3 つの相対誤差と κu\kappa u を並べます。真の分散はデータの浮動小数点数を有理数として厳密に計算します。

# Python 3.12.10 / NumPy 2.5.2(x86-64)/乱数種 20261006
from fractions import Fraction
import numpy as np
rng = np.random.default_rng(20261006)
z = rng.standard_normal(10**4)
u, n = 2.0 ** -53, len(z)
for m in (1e3, 1e5, 1e7):
x = m + z # 平均 m, 分散約 1
xs = x.tolist()
q = [Fraction(t) for t in xs] # 厳密な分散(有理数)
mq = sum(q) / n
v = sum((t - mq) ** 2 for t in q) / (n - 1)
one = (np.sum(x * x) - np.sum(x) ** 2 / n) / (n - 1)
two = np.sum((x - np.mean(x)) ** 2) / (n - 1)
mean, m2 = 0.0, 0.0 # Welford 法
for k, t in enumerate(xs, 1):
d = t - mean
mean += d / k
m2 += d * (t - mean)
wel = m2 / (n - 1)
kap = 2 * sum(abs(t) * abs(t - mq) for t in q) / ((n - 1) * v)
e = [abs(Fraction(t) - v) / v for t in (one, two, wel)]
print(f"{m:.0e} " + " ".join(f"{float(t):.2e}" for t in e)
+ f" {float(kap) * u:.2e}")
1e+03 4.30e-10 1.03e-16 2.69e-14 1.78e-13
1e+05 1.12e-06 6.05e-17 1.93e-12 1.78e-11
1e+07 7.57e-03 6.72e-17 2.39e-11 1.78e-09

列は mm、1 パス公式、2 パス公式、Welford 法の相対誤差、κu\kappa u です。

検算. (a) 既知値: 参照値はデータの有理数による厳密な分散です。(b) 別手法: 2 パス公式と Welford 法の誤差はどの mm でも κu\kappa u 以下で、後退安定なアルゴリズムに期待される範囲です。2 パス公式がとくに正確なのは、xix_i と xˉ\bar x の比が 1/21/2 と 22 の間にあるので xi−xˉx_i-\bar x が Sterbenz の補題(補題 4.1[浮動小数点数と丸め誤差])により厳密に計算されるからです(xˉ\bar x の誤差は残ります)。(c) 次数: mm を 100100 倍するごとに、κu\kappa u は 100100 倍(mm に比例)、1 パス公式の誤差は 2.6×1032.6\times10^3 倍・6.8×1036.8\times10^3 倍で、m2m^2 の比 10410^4 に近い増え方をし、m=107m=10^7 では κu\kappa u の 4×1064\times10^6 倍です。Welford 法の誤差は κu\kappa u の 1/71/7 から 1/701/70 の範囲で増えます。

演習 7.1易

f(x)=tan⁡xf(x)=\tan x の相対条件数を求め、xx が π/2\pi/2 に近いときと 00 に近いときの値を見積もれ。

解答

f′(x)=1/cos⁡2xf'(x)=1/\cos^2x なので κ(x)=∣x/(sin⁡xcos⁡x)∣=∣2x/sin⁡2x∣\kappa(x)=|x/(\sin x\cos x)|=|2x/\sin2x| です。x→0x\to0 では 11 に近づき、条件がよい問題です。x=π/2−hx=\pi/2-h(hh は小さい正の数)では sin⁡2x=sin⁡(π−2h)=sin⁡2h≈2h\sin2x=\sin(\pi-2h)=\sin2h\approx2h なので κ≈π/(2h)\kappa\approx\pi/(2h) です。たとえば h=10−6h=10^{-6} なら κ≈1.6×106\kappa\approx1.6\times10^6 で、入力の丸め(相対 uu)だけで約 6 桁が失われます。

演習 7.2標準

3 つの浮動小数点数の和を s^=fl(fl(a+b)+c)\hat s=\mathrm{fl}(\mathrm{fl}(a+b)+c) で計算する。成分ごとの後退誤差が γ2\gamma_2 以下であることを示し、前進誤差の評価 ∣s^−s∣/∣s∣≤γ2(∣a∣+∣b∣+∣c∣)/∣a+b+c∣|\hat s-s|/|s|\le\gamma_2(|a|+|b|+|c|)/|a+b+c| を 定理 4.3 の 3 から導け(オーバーフロー・アンダーフローはなく、a+b+c≠0a+b+c\ne0 とする)。

解答

標準モデルから s^=((a+b)(1+δ1)+c)(1+δ2)=a(1+δ1)(1+δ2)+b(1+δ1)(1+δ2)+c(1+δ2)\hat s=((a+b)(1+\delta_1)+c)(1+\delta_2)=a(1+\delta_1)(1+\delta_2)+b(1+\delta_1)(1+\delta_2)+c(1+\delta_2) で、誤差因子の積の補題から各係数は 1+θ1+\theta, ∣θ∣≤γ2|\theta|\le\gamma_2 の形です。よって s^=f(x+Δx)\hat s=f(\boldsymbol{x}+\Delta\boldsymbol{x})(f(a,b,c)=a+b+cf(a,b,c)=a+b+c)で ηx(Δx)≤γ2\eta_{\boldsymbol{x}}(\Delta\boldsymbol{x})\le\gamma_2 です。ff は 1 次式で ∂if=1\partial_if=1 なので、定理 4.3 の 3 の上限は (∣a∣+∣b∣+∣c∣)/∣a+b+c∣(|a|+|b|+|c|)/|a+b+c| で、主張の評価が出ます。これは κc×\kappa_{\mathrm{c}}\times 後退誤差の形です。

演習 7.3標準

大きな x>0x\gt0 に対して f(x)=x+1−xf(x)=\sqrt{x+1}-\sqrt{x} を計算する。(1) ff の相対条件数を求め、問題の条件がよいことを示せ。(2) 素朴な式の相対誤差がおよそ u⋅4xu\cdot4x になる理由を説明し、安定な式を与えよ。

解答

(1) f′(x)=12(1/x+1−1/x)=−f(x)/(2xx+1)f'(x)=\frac12(1/\sqrt{x+1}-1/\sqrt{x})=-f(x)/(2\sqrt{x}\sqrt{x+1}) なので κ(x)=x/(2x(x+1))<1/2\kappa(x)=x/(2\sqrt{x(x+1)})\lt1/2 です。(2) x+1\sqrt{x+1} と x\sqrt{x} はそれぞれ相対 uu 程度の誤差をもち、命題 4.2[浮動小数点数と丸め誤差] の倍率 (x+1+x)/f(x)=(x+1+x)2≈4x(\sqrt{x+1}+\sqrt{x})/f(x)=(\sqrt{x+1}+\sqrt{x})^2\approx4x で拡大されます。有理化した f(x)=1/(x+1+x)f(x)=1/(\sqrt{x+1}+\sqrt{x}) は引き算がなく、どの段も相対誤差が uu 程度なので、全体の相対誤差も数 uu に収まります。

  • N. J. Higham, Accuracy and Stability of Numerical Algorithms, 2nd ed., SIAM, 2002 — 第 1 章(前進誤差・後退誤差・条件数、分散の計算)、第 5 章(多項式)。
  • L. N. Trefethen, D. Bau III, Numerical Linear Algebra, SIAM, 1997 — Lecture 12(条件数)、Lecture 14・15(安定性と後退安定性)。
  • J. H. Wilkinson, Rounding Errors in Algebraic Processes, Prentice-Hall, 1963 — 多項式の根の感度と Wilkinson の多項式。
  • B. P. Welford, “Note on a method for calculating corrected sums of squares and products”, Technometrics 4 (1962), 419–420. doi:10.1080/00401706.1962.10490022
  • T. F. Chan, G. H. Golub, R. J. LeVeque, “Algorithms for computing the sample variance: analysis and recommendations”, The American Statistician 37 (1983), 242–247. doi:10.1080/00031305.1983.10483115

このテーマの 100 本ノック(50 問)

執筆: Claude Code(Opus 5.5)、Claude Code(Sonnet 5.5)・監査 2 回(Claude Code)・最終 2026-10-12

この記事の誤りを報告する ・運営: 夢現技研合同会社 ・料金 ・利用条件 ・特定商取引法に基づく表記

© 2026 夢現技研合同会社 ・コード例は MIT ライセンスです。