• 検索結果がありません。

do 文による反復処理

ドキュメント内 Maxima c (2007),,,,,. (ページ 186-191)

第 3 章 プログラム 175

3.1.3 do 文による反復処理

Maximaでは,do文を用いて反復処理を行います.

do文の基本構造

³

forh制御変数処理i h終了条件idoh本体i

µ ´

do文には,do文内部のみで用いられる局所変数があり,これを制御変数と呼びます. この制御変数 はdo文の中だけで効力を持ちます.それから,終了条件の判定を行い,終了条件を満さなければ,do 文の本体を実行し,それから制御変数処理で, 制御変数に変更を加え,再度,終了条件の判定を行う 事を反復します.

最初にh制御変数処理iの個所について述べます.

制御変数処理では,最初に制御変数に初期値を割当て,次に,反復処理で再度回って来ると,制御 変数に新しい値を割当てます.

ここで,最初の初期値の割当てでは,次の二つの同値な書き方があります.

制御変数の初期値の割当

³

h変数i:h初期値i h変数ifromh初期値i

µ ´

この制御変数の初期値の割当はどちらを用いても構いません.尚,初期値が1の場合,: h初期値i やfrom h初期値iは省略可能です.

次に,制御変数を一定の値で増加させたり,減少させたければ,do文の内部に, steph増分iを追 加します.この時,h増分iを正実数とすれば,通常の増分となり,負の実数とすれば,減少分になり ます. 尚,h増分iが1の場合はstep 1を省略する事が可能です

制御変数に何等かの函数を割当てたければ,next h制御変数の式iとすれば,iの値に h制御変数 の式iで計算した値が制御変数に割当てられます.

例えば,以下の二つの反復処理は同値になります.

制御変数の割当方法

³

do i from 1 step 2· · · do i:1 next i+2 · · ·

µ ´

これらは,全て制御変数iの初期値を1,増分を2とする反復処理を実行します. 最初の二つでは stepを用いて増分を定めています.最後のnextを用いたものでは,函数i+2で制御変数の値を定め ています.

これらの方法に加えて,リストを用いた制御変数の値の割当て方もあります.

リストを用いた制御変数の割当

³

for i in hリストi · · ·

µ ´

この場合,リストの成分には数値以外の函数や式を用いる事も可能です.

(%i10) for i in [1,2,3,4,5,6,7,8,9,10] do print(i);

1 2 3 4 5 6 7 8 9 10

(%o10) done

(%i11)for i in [sin,cos,tan] do print(subst(i,f,f(%pi/4)));

sqrt(2)

---2 sqrt(2)

---2 1

(%o17) done

この例では,最初にリスト[1,2,3,4,5,6,7,8,9,10]の元を表示し,最後の例では, f(%pi/4)のfに

sin,cos,tanを順番に代入した結果を表示させています.

do文の終了条件の与え方には,次の三種類があります.

do文の終了条件の与え方

³

thru 制御変数の境界値に達した時点で反復処理を終える.

unless 条件を満した時点で反復処理を終える.

while 条件を満さなくなった時点で反復を終える.

µ ´

ここで,終了条件を与える式は,MAXIMAの述語,即ち,trueかfalseかが判別可能な式です.unless を用いたdo文は,C等のrepeat-until文,whileを用いたdo文はwhile文に相当します.

thru,unlessとwhileを用いた例を以下に示します.尚,三種類ともに全て同じ反復処理,即ち,1か ら10迄の数を表示して終了,を実行するのです.

終了条件の例

³

for i:1 thru 10 do print(i);

for i:1 while i<= 10 do print(i);

for i:1 unless i>10 do print(i);

µ ´

尚,通常のdo文によって返される値はアトムのdoneです.函数returnを用いると, 本体の中で doから早目に抜けて必要な値を与える事に使えます. blockにあるdo文中のreturnはdo文を出 るだけで,block全体から出る訳ではありません.同様にgo函数もblock中のdo文から抜ける為に 使ってはなりません.

プログラムに関連する大域変数

³

変数名 初期値 概要

backtrace [] 函数リスト

dispflag true block文中の函数出力を制御

prederror true if文やis函数のエラーメッセージ出力を制御

errorfun false エラー発生時に起動させたい函数名

µ ´

backtraceはdebugmode:allの時に,入力された函数全てのリストを値として持ちます.

dispflagがfalseならば,block文の中で呼ばれた函数の出力表示を禁止します. 記号$のあるblock 文の末尾ではdispflagをfalseに設定します.

prederrorがtrueであれば,if文やis函数で,trueかfalseであるか述語の評価に失敗すると,何時 でもエラーメッセージが表示されます.

falseであれば,unknownが代りに返されます.

errorfunに引数を持たない函数名が設定されていれば,エラー発生時に, その函数が実行されま

す.この設定はbatchファイルで,エラーが生じた場合にMaximaを終了したり,端末からログアウ トしたい時に使えます.

block文内部で利用する函数

³

go(hラベルi) return(hi) break(h引数i,· · ·) catch(h1i,· · ·,hni) throw(hi)

µ ´

go函数はblock内部で指定したblock文中のラベルに移動する事に用いられます. ラベルとして

アトムを用い,このアトムは文の前に置きます.

block([x], x:1, loop,x+1, ..., go(loop), ...)

goの引数は同じblockの中で現われるラベルでなければなりません. goを含む別のblockにあ るラベルにgoを用いて移動する事は出来ません.

return函数はblock文から引数を伴って抜ける時に用います.場所はblock文の何処に置いても 構いません.

break函数は,h引数i の評価と表示を行い, (maxima-break)にて利用者がその環境を調べ,変 更する事が出来る様にします. (maxma-break)からはexit;を入力すれば計算が再開されます.

尚,Ctrl+a(ˆa)でmaxima-breakに何時もで対話的に入る事が出来ます.Ctrl+xはmaxima-break 内部で,本体側の処理を終了せずに, 局所的に計算を止める事に用いても構いません.

catch函数はthrowと対で用います.これは非局所的回帰(non-local return)で用いる函数で,最 も近いthrowに対応するcatchに行きます.その為,throwに対応するcatchが必ず必要で,そうで なければエラーになります. hiiの評価が何らのthrowの評価に至らなかった場合, catchの値は 最後の引数hniの値となります.

(%i51) g(l):=catch(map(lambda([x],

if x<0 then throw(x) else f(x)),l));

(%o51) g(l) := catch(map(lambda([x], if x < 0 then throw(x) else f(x)), l)) (%i52) g([1,2,3,7]);

(%o52) [f(1), f(2), f(3), f(7)]

(%i53) g([1,2,-3,7]);

(%o53) - 3

函数gは,lが非負の数のみであればlの各要素に対するfのリストを返します. それ以外では,g はlの最初の負の要素を捉えて,それを放します.

throw函数はhiを評価し,近くにあるcatchに値を投げ返します. throwはcatchと一緒に使 われます.

エラー処理を行う函数

³

errcatch(h1i,· · ·,hni) error(h引数1i,· · ·,h引数ni) errormsg()

µ ´

errcatch函数は引数を一つづつ評価して,エラーが生じなければ最後の値のリストを返します.,

任意の引数の評価でエラーが生じた場合,errcatchはエラーを捉えて即座に[](空のリスト)を返しま す.この函数はエラーが生じていると疑われるbatchファイルで,エラーを捉えなければ怱ちbatch を終了させる様にすると便利です.

error函数は引数の評価と表示を行い,Maximaのトップレベルか,errcatchにエラーを返します.

エラー条件を検知した場合や,Ctrl+ˆが入力出来ない場所なら何処でも函数を中断させられるので 便利です.

大域変数errorにはエラーを記述するリストが設定されており,最初のものは文字列で,残りの対

象は問題を起しているものです.

errormsg函数は最新のエラーメッセージを再表示します.変数errorにはエラーを記したものの

リストが設定されており,最初は文字列で,残りは問題の対象です.

ttyintfun:lambda([],errormsg(),print(””))で利用者中断文字(ˆ u)をメッセージの再表示を行う 様に設定します.

ドキュメント内 Maxima c (2007),,,,,. (ページ 186-191)