周期補間の方法を説明する.これは,周期的な関数の値がいくらか与えられた場合に,与えられていない点の値を補間により予測する方法である.周期的な関数とは,\(f(x) = f(x + T)\)を満たすような\(T\)が存在する関数\(f\)のことを言う.\(T\)はこのときこの関数の周期と呼ばれる.例えば,\(\sin, \cos\)は\(T=2\pi\)の周期関数である.ここではこのような周期関数の補間法を説明する.周期補間法とここでは呼ぶが,いつ誰が考えついたかもわからないくらい,当然のように使われる方法である.一般的にはに示すような周期関数も存在する.
補間の例を示すに当たり,まず前提を説明する.\(x_i = ih\)で表されている飛び飛びの点(格子点と普通呼ぶ)において,関数の値\(y_i = y(x_i)\)が定義されているとする.添字\(i\)(インデックスとも言う)は\(i=0,1,...,N\)の値を取り,最初と最後の\(y\)の値は等しい,つまり\(y_0 = y_N\)であるとする.もし,\(h=2\pi/N\)とするならば,このような関数として,\(\sin, \cos\)が挙げられる.ここでは,の例を考える.考える周期関数は,の中央の6点(黒5つ,白中ぬき1つ)の点で表される区間線形関数(直線で点を結んだもの)を繰り返したものである.白抜きの点は,原点の黒の点と同じであるとする.よって実際に記録しておくべき値を持つ点の数は\(5\ (=N)\)であり,\(i=N-1\)までが有効な添字の範囲となる.周期は見ての通り,\(T=5h\)である.
簡単のために,まずは,\(0\leq x \lt 5h\)の場合を考えよう.このとき,周期性も\(x \lt 0\)の場合も考える必要はない.\(x\)が属する2つの格子は,原点から\(x\)の場所までに\(h\)の幅がいくつ入るかを数えればよいため,\(x/h\)の値の整数部分を見れば良い.よって,
補間に用いる両側の添字を,図より,\(i_1 = i, i_2 = i+1\)と求めようと思うが,\(i=N-1\)のときに,\(i_2 = N\)となり,有効な添字の最大値\(N-1\)を超えてしまうが,\(i=N\)の場所の値はもともと\(i=0\)の場所と同じであるから,これを用いることを考える.これは,次のように添え字を割り算のあまり(剰余演算子\(\%\)による結果)で修正することで実現できる.
ここまでで,補間値\(y \)を次の通り求めることができる.
次に,\(h5 \leq x\)を含む,\(0\leq x\)の少し一般化した場合を考える.これは,格子点が基準となる範囲,ここでは\(i=0,1,...,4\)を超え,繰り返し終わりなく定義されていると考えれば,わかりが良いと思う.永遠と幅\(h\)で繰り返されていると考えるため,\(x\)の場所までの格子数は,\(\mathrm{int}(x/h)\)であるから,その直前の格子の添字はと同様に,
以上で,により周期補間のための添字を求めれば,補間値をで求めることができる.結局,周期性を仮定しない場合との違いは,添字の計算でを用いるか,を用いるかだけである.しかし,はの場合を含むため,常に,を用いれば良い.
負の場合は,だいぶ難しい.正の領域における周期補間,の場合と同様に,\(i = \mathrm{int}(x/h)\)としたら,これは,原点から数えた\(h\)の幅が入る数を与えるため,この\(i\)を用いると,\(x_i = hi\)と\(x_{i+1}=(i+1)h\)の間に\(x\)が入らなくなる.格子が一つ分正の方向にずれてしまう.ただし,どの場合も,ちょうど一つ分ずれるだけであるから,
次に,正場合と同様に,\(y_{i}=y_{i_1}, y_{i+1} = y_{i_2}\)となる\(i_1, i_2\)を求める.今周期が\(T=hN\)だから,負の方向に添字\(i\)が\(N\)進むごとに,\(i=0\)の場所と同じ値を取ることがわかる.うまく想像ができない場合は,を見よ.可能な限り絵を描いたほうが理解が良いと思う.の真ん中のグラフの格子点に左のグラフのそれぞれの格子点が重ねることを考えれば,格子の添字\(i\)というのは,整数の添字\(j=...,-(N+1), -N,...,-2,-1,0,1,...,N,...,2N,...\)に対して,
\(x\)の値が任意の場合における処理を次にまとめる.
関数\(f(x)\)の値が,\(h=0.1\)間隔で,格子点\(x_i = hi, i=0,1,...,N-1, N\)上に,\(f_i = f(x_i)\)として,\((f_0, f_1, ...,f_N) = (0.1,0.2, -0.1, 0.2, 0.1)\)と定義されている.\(f_0 = f_N\)であり,\(N=4\)とする.この格子点以外の場所の値は,線形補間により\(f\)の値を定める.また,\(f\)は周期\(hN\)の周期関数であるとする.この\(f\)について,任意の\(x\in\sR\)に対し,\(f(x)\)の値を周期補間により求めるプログラムを実装する.
上記課題の結果を次に示す.ソースコードをperiodic.pyへ示す.正しく周期補間ができていることがわかる.
\(\sin, \cos\)の値をEuler 法により格子点\(t_i=ih, i=0,1,...,NM, h=2\pi/(NM)\)に対し求め,周期補間により任意の\(x\in \sR\)に対して\(\sin (x), \cos (x)\)の値を与えるプログラムを実装する.この方法ができれば,無理数を取り,多項式で表せない\(\sin, \cos\)の値を高速かつ実用上十分な精度で求める関数が,プログラム開始時にEuler法を計算するだけで得られる.ただし,Euler法は大変多くの格子を用意しなければ精度が保てない一方,補間の精度はEuler法で必要なほど多くは必要なため,Euler法で得られる結果を間引いて,保存する.間引きの間隔は\(M\)であるとする.つまり,補間のための点は\(N\)点のみ記録する.
上記課題の,\(N=32, M=256\)の場合の結果を次に示す.ソースコードをperiodic.pyに示す.補間のために保存してある点は\(N=32\)点だけであるが,もともと\(NM=8192\)分割した\(h\)で計算した精度の比較的高い結果から得られた\(32\)点であるから,これらの点による補間は精度が高いことが期待できる.実際に,見た目には高い精度で補間ができていることがわかる.
\(N=32, M=2\)の場合の結果を次に示す.この場合,オイラー法の精度が足りず,次のように不連続な場所が現れる.ソースコードをperiodic-H.pyへ示す.
\(N=64, M=1\)で,\(i = NM\)の結果を lx, ly へ代入してしまい,かつリストの大きさでlen(lx)あるはlen(ly)の値を設定した結果を次に示す.ここで,リストの大きさは最初と最後が重複しているため,\(N+1\)となっているはずである.結果を見ると,周期の境界付近で,一定の値の場所が確認でき,不連続な補間となっている.ソースコードは periodic-Np1.py に示す.
\(\theta \to |\theta|\)と変換してしまっている場合の結果を次に示す.\(N=32, M=256\)としている.sin が偶関数でないため,絶対値を用いた方法では正しく補間ができないはずで,結果を見てもそれがわかる.periodic-abs.pyへソースコードを示す.
\(\theta \lt 0\)の場合に\(i = \mathrm{int}(\theta/h) -1 \)の処理をしなかった場合の結果を次に示す.\(N=32, M=256\)としている.periodic-nonegative.pyへソースコードを示す.
\(N=256, M=256\)など,補間点\(N\)を増やせば,以下のように見た目には分かりづらい精度の悪さに収まる.しかし,細かい部分では正しく補間でできていないため,実用に用いることはできない.