|
2.2.2 関数を反復的に適用する
計算プログラムを書いていると,ある操作を繰り返し行う必要がでてくる.そのようなときは,強力な構造体Nest,NestListを使い反復操作を行うことができる.

引数が1個の関数を繰り返し適用する
Nest[f, x, n]は,関数の「名前 」fを取り出し,この関数をxにn回繰り返し適用する.
In[1]:= Nest[f, x, 4]
Out[1]= 
重ねてネストさせた結果をリスト構成にする.
In[2]:= NestList[f, x, 4]
Out[2]= 
簡単な関数を定義しておく.
In[3]:= recip[x_] := 1/(1 + x)
Nestを使い,関数を繰り返し適用する.
In[4]:= Nest[recip, x, 3]
Out[4]= 
NestとNestListにより固定された回数だけ関数を適用することができる.結果に変化がなくなるまで関数を適用したい時は FixedPointおよびFixedPointListを使用する.

結果に変化がなくなるまで関数を適用する
これは, をニュートン法で近似するときにステップを指定して計算する関数である.
In[5]:= newton3[x_] := N[ 1/2 ( x + 3/x ) ]
始点 で開始させ,近似関数を5回ネストさせる.
In[6]:= NestList[newton3, 1.0, 5]
Out[6]= 
関数FixedPointを使うことで,結果に変化がなくなるまで newton3を自動的に繰り返し適用させることができる.
In[7]:= FixedPoint[newton3, 1.0]
Out[7]= 
変化の結果を順に並べる.
In[8]:= FixedPointList[newton3, 1.0]
Out[8]= 

テストが失敗するまで関数を反復適用する
与えられた数を2で割る関数.
In[9]:= divide2[n_] := n/2
結果が偶数でなくなるまで繰り返しdivide2を適用する.
In[10]:= NestWhileList[divide2, 123456, EvenQ]
Out[10]= 
FixedPointListのように,2つの連続した結果がもはや互いに異なるとは判断されなくなるまでnewton3を反復適用する.
In[11]:= NestWhileList[newton3, 1.0, Unequal, 2]
Out[11]= 
以前に見られた結果が再現されるまで継続する.
In[12]:= NestWhileList[Mod[5 #, 7]&, 1, Unequal, All]
Out[12]= 
Nestのような関数操作では,引数が1つの関数fを取り,それを繰り返し適用する.そして反復の各ステップにおいて,その直前のステップの結果をfの新たな引数として使う.
この考えを,引数が2つの関数にも使えるように一般化しておくことは大切である.その場合も,関数を繰り返し適用することができるが,得られる各結果は,次の関数適用で必要な2つの引数のうち1つしか提供することができない.そこで,別に2つ目の引数群をリストで用意しておき,そこから第2引数を逐次取り出し各ステップに当てる,という手順を使うと便利である.

2引数の関数の繰返し適用
これは,FoldListの実行例である.
In[13]:= FoldList[f, x, {a, b, c}]
Out[13]= 
Foldは,FoldListの生成するリストの最終要素だけを返す.
In[14]:= Fold[f, x, {a, b, c}]
Out[14]= 
累積和のリストを返す.
In[15]:= FoldList[Plus, 0, {a, b, c}]
Out[15]= 
FoldとFoldListの機能を使うことで,読みやすくまた効率的なプログラムを書くことができる.場合によっては,FoldとFoldListを,第2引数でインデックスされている関数の族を単純なネストで生成するものと考えるとよい.
前回の値を次の桁に繰り上げていく関数を定義し,nextdigitと呼ぶ.
In[16]:= nextdigit[a_, b_] := 10 a + b
まるで組込み関数のFromDigitsのようになった.
In[17]:= fromdigits[digits_] := Fold[nextdigit, 0, digits]
関数の動作碓認をする.
In[18]:= fromdigits[{1, 3, 7, 2, 9, 1}]
Out[18]= 
|