| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
9.1 プログラムの流れについて 9.2 プログラムの流れに関する諸定義
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
MACSYMAには反復処理にDOループとGOと云ったより原始的な構造もある。
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
1. 三種類の変種があり、各々は終了条件のみ異なる。
初期値、増分、境界と本体は如何なる式でも良い。増分が1であれば、"STEP 1"は 省略しても良い。
DO文の実行は最初に初期値を変数に割当てる(それ故、その変数を制御変数と呼ぶ)。
その終了条件が満される迄、(1)から(3)までの処理が繰り返し実行される。幾つか の終了条件も与えても良く、その場合は、それらの内のどれか一つでも条件を満した 時にDO文が終了する。
一般的に、THRUテストを満足させるのは、増分が非負であれば制御変数がその境界値 よりも大きくなった時、増分が負であれば制御変数がその境界値よりも小さくなった 時である。増分と境界は不等号が判別可能でさえあれば非数値式であっても構わない。 しかし、DO文が入力された時に、増分が構文的に負(例えば負の数)でない限り、 MACSYMAはDO文を実行する時にそれが正であると仮定する。もし、それが正でなければ、 DO文を正しく終了する事が出来ない。
境界値、増分と終了条件はループの間の各時点で評価される事に注意する。それ故、 これらの任意のものが膨大な計算を引き起すものの、その一方で、生成された結果が 本体全ての実行の間に変化しないものであれば、DO文に対して効果的な値を変数に 設定して、この変数をDO文で用いるのがより効率的である。
通常DO文によって返される変数は原子のDONEであり、MACSYMAで全ての文が返す値と 同じである。ここで、関数RETURNは本体の中でDOから早目に抜けて任意の必要な値を 与える為に用いて良い。しかし、BLOCKにあるDO文中のRETURNはDO文を出るだけで、 BLOCKから出る訳では無い事に注意せよ。更に、GO関数もBLOCK中のDO文から抜ける為 に使ってはならない事に注意せよ。
制御変数はDO文に対して常に局所的であり、それ故、任意の変数はDO文の外側と同名 の変数の値に影響を与えずに利用する事が可能である。制御変数はDO文が終了した後 に不定値になる。
(C1) FOR A:-3 THRU 26 STEP 7 DO LDISPLAY(A)$ (E1) A = -3 (E2) A = 4 (E3) A = 11 (E4) A = 18 (E5) A = 25 |
関数LDISPLAYはこの様に中間ラベルを生成する;しかし、DISPLAYはそうでは無い。
(C6) S:0$ (C7) FOR I:1 WHILE I<=10 DO S:S+I; (D7) DONE (C8) S; (D8) 55 |
C7での条件はUNLESS I>10やTHRU 10とも同値である事に注意せよ。
(C9) SERIES:1$
(C10) TERM:EXP(SIN(X))$
(C11) FOR P:1 UNLESS P>7 DO
(TERM:DIFF(TERM,X)/P,
SERIES:SERIES+SUBST(X=0,TERM)*X^P)$
(C12) SERIES;
7 6 5 4 2
(D12) X X X X X
-- - --- - -- - -- + -- + X + 1
96 240 15 8 2
上の例ではe^sin(x)のTaylor級数の8個の項を与えている。
(C13) POLY:0$
(C14) FOR I:1 THRU 5 DO
FOR J:I STEP -1 THRU 1 DO
POLY:POLY+I*X^J$
(C15) POLY;
5 4 3 2
(D15) 5 X + 9 X + 12 X + 14 X + 15 X
(C16) GUESS:-3.0$
(C17) FOR I:1 THRU 10 DO (GUESS:SUBST(GUESS,X,.5*(X+10/X)),
IF ABS(GUESS^2-10)<.00005 THEN RETURN(GUESS));
(D17) - 3.1622807
|
この上の例では10の負の平方根をNewton-Raphson法を用いて最大10回の反復計算を 行っている。収束判定で値が見付からなければ"DONE"を返すものである。
DO文の追加形式
制御変数に対して何時も加える量の代りに、各々の反復で別の手法に代えたい事もあ るだろう。この場合、"NEXT式"を"STEP増分"の代りに用いて良い。これで制御変数に はループを通して各時点で式を評価した値が設定される。
(C1) FOR COUNT:2 NEXT 3*COUNT THRU 20
DO DISPLAY(COUNT)$
COUNT = 2
COUNT = 6
COUNT = 18
|
FOR 変数:値 ... DO ...構文の代りに、FOR 変数 FROM 値 ... DO ...が使える。 "FROM 値"をSTEPやNEXTの値や終了条件の後に置く事も可能である。"FROM 値"が省略 されると1が初期値として用いられる。
時には反復処理の実行で、制御変数が実際に使われていないものに興味を持つかもし れない。そこで、終了条件のみに情報の初期化と更新を、次の貧弱な初期推定値を用 いて5の平方根を計算する次の例の様に省略する事も可能である。
(C1) X:1000 (C2) THRU 10 WHILE X#0.0 DO X:.5*(X+5.0/X)$ (C3) X; (D3) 2.236068 |
もし、望ましければ、終了条件でさえもすっかり省略し、不定値のまま本体を評価し 続ける"DO 本体"を与えて良い。この場合、RETURN関数をDO文の実行を中断する為に 用いなければならない。
(C1) NEWTON(F,GUESS):=
BLOCK([NUMER,Y],
LOCAL(DF),
NUMER:TRUE,
DEFINE(DF(X),DIFF(F(X),X)),
DO (Y:DF(GUESS),
IF Y=0.0 THEN ERROR("Derivative at:",GUESS," is zero."),
GUESS:GUESS-F(GUESS)/Y,
IF ABS(F(GUESS))<5.0E-6 THEN RETURN(GUESS)))$
(C2) SQR(X):=X^2-5.0$
(C3) NEWTON(SQR,1000);
(D3) 2.236068
|
(RETURNが実行された時、GUESSの現行の値がDO文の値として返される事に注意せよ。 BLOCKから抜けるとDO文の値はBLOCKの値として返される。何故なら、 DOはBLOCKの 中で最後の文の為である)。
DO文のもう一方の形式がMACSYMAで利用可能である。その構文は:
FOR 変数 IN リスト [end-tests] DO 本体 |
リストの成分は任意の式であり、本体の各反復では変数に続けて割り当てられる。 オプションのend-testsはDO文の実行を終了させる為に用いる事が可能で、さもなくば、 リストを消耗した時や本体でRETURNが実行された時に終了する(実際、リストは任意の 原子でない式や連続した成分が取られていても良い)。
(C1) FOR F IN [LOG, RHO, ATAN] DO LDISP(F(1))$
(E1) 0
(E2) RHO(1)
%PI
(E3) ---
4
(C4) EV(E3,NUMER);
(D4) 0.78539816
|
ERRORMSG();は最近のエラーメッセージを見せる適切な方法である。
ERRORFUN デフォルト値: [FALSE] - エラーが発生すると何時でも実行される引数を 持たない関数の名前を設定する。これはBATCHファイルでエラーが生じた場合、 MACSYMAを殺したり、端末からログアウトしたい時に便利である。
TTYINTFUN:LAMBDA([],ERRORMSG(),PRINT(""))$ で利用者中断文字(^U)を メッセージの再表示を行う様に設定する。
例えば:
BLOCK([X],X:1,LOOP,X+1,...,GO(LOOP),...) |
IF 条件 THEN 式1 ELSE 式2 |
演算子名 記号 種類 よりも大きい > 関係を記述する中置詞(infix) に等しい = , EQUAL " " に等しくない # " " よりも小さい < " " より以上 >= " " より以下 <= " " and AND 論理中置詞(infix) 又は OR " " 否定 NOT 論理前置詞(PREFIX) (* 訳者注 前置詞(PREFIX)と中置詞(INFIX)は演算子を、その引数の置き方で区分したもの。 前置詞(PREFIX):OP <-> OP X (e.g. NOT X=1,...) 中置詞(INFIX): OP <-> X OP Y (e.g. X=Y,X*Y,...) 詳細は前置詞(PREFIX)と中置詞(INFIX)の項目を参照せよ。 *) |
MAPERROR[TRUE] - FALSEであれば、全てのMAP関数は
MAPERRORがTRUEであれば、上記の状態でエラーメッセージを出す。この関数の利用 目的の一つが関数(例えば、PARTFRAC)を非常に大きな式の各項に写像する事であり、 その式は計算の過程でリストの保管場所を消耗する為、関数を式全体に用いる事には 適さないものである。
(C1) MAP(F,X+A*Y+B*Z);
(D1) F(B Z) + F(A Y) + F(X)
(C2) MAP(LAMBDA([U],PARTFRAC(U,X)),X+1/(X^3+4*X^2+5*X+2));
1 1 1
(D2) ----- - ----- + -------- + X
X + 2 X + 1 2
(X + 1)
(C3) MAP(RATSIMP, X/(X^2+X)+(Y^2+Y)/Y);
1
(D3) Y + ----- + 1
X + 1
(C4) MAP("=",[A,B],[-0.5,3]);
(D4) [A = - 0.5, B = 3]
|
MAP(fn,exp1,exp2,...)) |
MAPERRORがTRUEの場合、上の二つの状況であればエラーメッセージが出力される。
例えば:
(C1) EXP:(A^2+2*A+1)*Y + X^2$
(C2) SCANMAP(FACTOR,EXP);
2 2
(D2) (A + 1) Y + X
|
ここでSCANMAPは与えられたFACTOR関数をexpに含まれる部分式に作用させる; もし、expの別の形式がSCANMAPに対して表現されていれば、結果が異なるかもしれ ない事に注意せよ。それ故、SCANMAPをexpの展開した形式に適用してもD2が修復され ない。
(C3) SCANMAP(FACTOR,EXPAND(EXP));
2 2
(D3) A Y + 2 A Y + Y + X
|
以下に別の例があり、そこではSCANMAPが指数を含めた全ての部分式に対して与えら れた関数を再帰的に適用する。
(C4) EXPR : U*V^(A*X+B) + C$
(C5) SCANMAP('F, EXPR);
F(F(F(A) F(X)) + F(B))
(D5) F(F(F(U) F(F(V) )) + F(C))
|
SCANMAP(function,expression,BOTTOMUP)は、例えば、Fが未定義であれば、 "ボトムアップ"式にfunctionをexpに作用させる。
SCANMAP(F,A*X+B) ->
F(A*X+B) -> F(F(A*X)+F(B)) -> F(F(F(A)*F(X))+F(B))
SCANMAP(F,A*X+B,BOTTOMUP) -> F(A)*F(X)+F(B)
-> F(F(A)*F(X))+F(B) ->
F(F(F(A)*F(X))+F(B))
|
この場合、同様の答を両方の方法で得る。
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |