四則演算 + – * /


Forthでも普通の四則演算がわからないという人は、ほとんどいないと思う。変数を使わずスタック上で実施するので、コード面は初めは分りにくいということはあるかも知れないが、普通は数分もあれば慣れる。

記号としては、足し算は + 、引き算は - 、掛け算は * 、割り算は / 、なのでごく普通である。これらもワードなので、前後は空白文字で空ける。変数名や数字とつなげてしまってはいけない。これらは整数演算であり、入力も出力も整数である。割り算は余りは捨ててしまう。二つの整数をデータスタックから取り、結果をスタックに置く。"a b -" は"a 引く b"であり、"a b / " は "a 割る b"である。
   \ スタックの状態 : x y
-  \ スタックの状態 : x-y
なお、スタックはLIFOだからということで、引算のとき、a b -とするなら、まずトップのbをスタックからとり、次にaを取ってbから引く、と考えてしまいかねない。そうすると、b-aとなってしまうが、そうはならない。これは、二項演算では二つの値を同時にスタックから受け取ると考えればいいのだが、初めは混乱するかもしれないので注意。引算では、下の値から上の値を引くし、割り算では、下の値を上の値で割るのが通常である。

ところで、割り算 / のとき、後の項(スタックのトップ)が分母になるが、これが0だとx86は割り込みが入ってOSが例外を投げる。
これを受け取る機構が無いソフトウェアは、その場で落ちるので気をつけなければならない。内部的にフラグをいじれば止められるようだが、バグ発見のためには、
Onにしておいた方が良いのかも知れない。
iMopsではデフォルトではexceptionが投げられ、クラッシュする。PowerMopsでは静かに結果としてNaNを返す。



数値変換

やや場違いだが、数値処理に関連することは明らかなので、スタックの数値の符号を変えるワードNEGATEをここに挙げておく。
NEGATE    ( n -- -n )   \ 符号を替える
もちろん負の数は正になる。
さらに、ABSは絶対値を取る演算である。正ならそのまま、負ならば符号を替える。
ABS ( n -- u )
また、計算上も用いるものとして、2つの値の大きい方、あるいは小さい方を取るMAXMINも挙げておく。
MAX  ( n1 n2 -- n )  \ nはn1、n2のより大きい方の値。等しいときはどちらか。つまりうるさく言えば、より小さくない方の値。
MIN  ( n1 n2 -- n )  \ nはn1、n2のより小さい方の値。(より大きくない方の値)

割り算の拡張


割り算の余りを出す計算MOD、余りと商の両方を出す計算/MODがある。
例えば:
234 10 MOD    \ -- 4  つまり、234を10で割った余り
345 10 /MOD   \ -- 5 34   トップが商であることに注意

商をq、余りをrとしてスタック効果は:
MOD    ( n n' -- r )   \  n=r (mod n')
/MOD    ( n n' -- r q )

また、割り算に関しては、被演算項を正の数と見なして計算する、Unsignedの演算も定義されている。

u/    ( u u -- uq )       \  符号なしの割り算
uMOD  ( u u -- ur )     \ 符号なしのMOD
u/MOD    ( u u -- ur uq )   \ 符号なしの/MOD

短縮演算


スタック値を1だけ増減する場合と、2倍または2分の1にする場合について、演算を簡約したワードが定義されている。これらは
forth標準である。

1+    ( n -- n+1 )
1-    ( n -- n-1 )
2*    ( n -- 2n )
2/    ( n -- n/2 )    \ 余りは切り捨て

説明は不要だろう。

Mopsでは、この種の簡略演算ワードを、もう少し余分に定義している。追加分は:

2+    ( n -- n+2 )
3+    ( n -- n+3 )
4+    ( n -- n+4 )

2-    ( n -- n-2 )
3-    ( n -- n-3 )
4-    ( n -- n-4 )

3*    ( n -- 3n )
4*    ( n -- 4n )
4/    ( n -- n/4 )    \ 余りは切り捨て 

である。

普通に計算しても同じだが、概していえば、こちらの方が速い(特に、掛け算と割り算)。

計算は基本的なものはこんなものだろう。
続いては、ページを変えて、ビットの論理演算と、ビットシフト操作に関するワードについて述べる。






最終更新:2019年12月13日 22:33