FORTHはもともと「整数とスタック」を中心にした極めて単純な構造を持つ言語である。しかし科学技術計算や物理シミュレーションなど、実数を扱う場面では整数だけでは不十分だ。そこで登場するのが、gforth における 浮動小数点演算(floating-point arithmetic) である。本章では、FORTH独自の「浮動スタック(f-stack)」の仕組みを理解し、f+, f-, f*, f/ などの基本演算から、平方根・指数・三角関数までを学ぶ。
gforthにおける浮動小数点の基本構造
整数演算とは異なり、浮動小数点演算は 浮動小数点スタック(f-stack) を使って処理される。これにより、整数スタックと混在しても衝突せず、安全に計算できる。
浮動小数点数として解釈されるためには、数値に E (指数) が含まれている必要がある。 1.23E 1E 0.e これらは浮動小数点スタックに積まれる。
各スタックは独立しており、F@, F!, S>F, F>S などのワードを使って整数スタックと浮動スタックの間でデータを移動する。
基本ワードと操作例
代表的なf系ワードを以下にまとめる。
| 操作 | ワード | 意味 | スタック効果 (f-stack) |
|---|---|---|---|
| 加算 | f+ |
浮動値を加算 | ( f1 f2 -- f3 ) |
| 減算 | f- |
f1 − f2 | ( f1 f2 -- f3 ) |
| 乗算 | f* |
f1 × f2 | ( f1 f2 -- f3 ) |
| 除算 | f/ |
f1 ÷ f2 | ( f1 f2 -- f3 ) |
| 平方根 | fsqrt |
√f | ( f -- f' ) |
| 指数 | fexp |
e^f | ( f -- f' ) |
| 対数 | fln |
ln(f) | ( f -- f' ) |
| 正弦 | fsin |
sin(f) | ( f -- f' ) |
| 余弦 | fcos |
cos(f) | ( f -- f' ) |
| 代入・取得 |
F!, F@
|
メモリへ格納・取得 | ( f addr -- ) / ( addr -- f ) |
整数⇔浮動変換のための橋渡しワード:
| ワード | 説明 | スタック効果 |
|---|---|---|
S>F |
整数を浮動小数に変換 | ( n -- f ) |
F>S |
浮動を整数に変換 | ( f -- n ) |
F. |
浮動数を表示 | ( f -- ) |
浮動リテラルの入力
gforthでは、数値の後ろに小数点を付けると自動的に浮動数とみなされる:
1.23e2 f. \ → 123.0
3.14159e f. \ → 3.14159
ただし整数と区別するため、末尾に指数表記(e)を必ず付ける。
fスタックの挙動を観察する
浮動スタックの状態を確認するには .S ではなく F.S を使う。
1e 2e f+ f.s
<1> 3.0000000000E0
これは、整数スタックとは別に fスタックが存在していることを示している。整数スタックを表示する.Sとは完全に独立している点に注意。
例題1:円の面積を求める
半径を入力し、円の面積(πr²)を計算する。
3.1415926535e FCONSTANT PI
\ 円の半径から面積を求める
: AREA ( f: r -- f: area )
fdup f* PI f* ;
\ 半径5の円の面積
5e AREA f. \ → 78.5398163375
例題2:指数・対数の計算
自然対数と指数関数を組み合わせて確認してみよう。
1.0e fln f. \ → 0.
2.0e fexp f. \ → 7.38905609893065
また、fexp fln の組み合わせで恒等性を確認できる:
3.5e fln fexp f. \ → 3.5
これにより、FORTHがIEEE準拠の浮動演算を正しく実装していることがわかる。
例題3:三角関数
fsin, fcos, ftan などのワードはラジアン単位で動作する。
例えば 90° = π/2 を代入して確認する。
3.1415926535e FCONSTANT PI
PI 2e f/ fsin f. \ → 1.
PI 2e f/ fcos f. \ → 0.0000000000448965921697616
角度を度単位で扱いたい場合は、事前にラジアン変換する:
度 × π / 180 = ラジアン
: DEG>RAD ( f: deg -- f: rad )
PI 180e f/ f* ;
メモリとのやり取り:f@ と f!
浮動変数を使うには、CREATEとf!/f@を組み合わせる。
CREATE TEMP 1 FLOATS ALLOT \ 浮動1セル分のメモリを確保
37.5e TEMP f! \ 書き込み
TEMP f@ f. \ → 37.5
ここで FLOATS は、環境依存の浮動数サイズを正しく確保するための定数である(通常は8バイト)。
整数との相互変換
整数で受け取った値を浮動計算に使いたい場合、S>Fを使う。
10 S>F 3.0e f/ f. \ → 3.33333
逆に、浮動演算の結果を整数に戻すには F>S。
2.9e F>S . \ → 2 (小数部切り捨て)
応用例:単利計算プログラム
利率 r(%/年)、期間 t(年)、元本 p から単利を求める。
: INTEREST ( f: p r t -- f: i )
f* f* 100e f/ ; \ p * r * t / 100
10000e 3.5e 5e INTEREST f. \ → 1750.
浮動演算なら、金利・時間・温度・面積・速度など、連続的な量をそのまま扱える。
応用例:ニュートン法による平方根近似
整数では誤差が生じる近似計算も、浮動数なら滑らかに実装できる。
: FSQRT-N ( f: x -- f: root )
FDUP 0E F<= IF
FDROP 0E EXIT
THEN
FDUP FSQRT \ 初期値
10 0 DO
FOVER FOVER F/ F+ 2E F/
LOOP FNIP
;
9E FSQRT-N F. \ → 3.
2E FSQRT-N F. \ →1.41421356237309
0E FSQRT-N F. \ → 0.
このプログラムは、$\sqrt{N}$ を見つけるために、以下の有名な漸化式(反復計算)を使用している。
$x_{n+1} = \frac{1}{2} \cdot \left( x_n + \frac{N}{x_n} \right)$
fスタックと通常スタックの同時利用
整数でループ回数を管理し、fスタックで計算を行う例:
: SUM-UP ( n -- f: sum )
0E \ 初期値
1 + 1 DO
I S>F F+ \ fスタック上で計算
LOOP
F>S ; \ 通常スタックに戻す
整数スタックのIとfスタックが明確に分離されていることがわかる。この二重構造はFORTHならではの柔軟な特徴である。
練習課題
- 半径を入力して円周長(2πr)を求めるワードを作成せよ。
-
fsin・fcosを用いて、任意角度のサイン・コサイン表を出力するプログラムを書け。 - 台形法で関数
f(x)=x^2を 0〜1 の範囲で積分し、結果を小数で表示せよ。 -
f@とf!を使って温度記録を保持・更新するプログラムを作成せよ。