この章ではMindが扱う2つの数値の型である
整数と
小数について解説する。
この項では整数を処理する方法を解説する。
全ての演算は符号付き32ビット整数として行われる。(倍精度整数という型もあるが本版ではまだ扱わない)
第4章でも述べたが、Mindのデータの型(あるいは演算の型)は、変数の型とは1対1には対応しない。整数を例にとれば、変数には3種類の型(変数/ワード変数/バイト変数)があるが、演算は常にそのうち最も大きな型である符号付き32ビットで行われる。
各処理単語について、スタックデータ配置(以下、スタック仕様とかパラメータ仕様とか呼ぶ)を統一した表記で説明する。この表記は本章に限らず、以降の章すべてに共通するものとする。
「加える」のスタック仕様を例にとる。
構文=
<数値1>と <数値2>を 加える → <数値>
↑ ↑
処理前にスタックに積むデータ スタックに返されるデータ
(実行により消費される)
上記はデータをスタック渡しにできる場合であるが、変数に副作用を与えるような処理単語では、その変数を明記しなければならない。また、このような処理単語では、その変数名に特定の送り仮名を振ることが強要される。
「クリア」がその例である。次のように表記するものとする。
構文=
副作用を与える変数 スタックが空になって帰ることを示す
↓ ↓
<変数>を クリアする → ・
↑
アンダーラインのある送り仮名は必須
整数変数に副作用を与えるもの
第4章(データ型と変数)でも簡単に説明したが、整数変数に値を代入したり更新を行う単語群を示す。
以下の解説では通常の変数としての例を示すが、実際には配列・構造体・型紙の要素となる変数にも適用できることを覚えておいて欲しい。
まず以下のものは、変数のみを指定し、それに副作用を与えるものである。
構文=
<変数>
を クリア → ・
(0を代入する)
<変数>
を セット → ・
(1を代入する)
<変数>
を 一つ増加 → ・
(変数の内容を一つ増加)
<変数>
を 一つ減少 → ・
(変数の内容を一つ減少
(複数変数を一括処理する場合)
<変数>と <変数>と ・・ <変数>を クリア → ・
<変数>と <変数>と ・・ <変数>を セット → ・
<変数>と <変数>と ・・ <変数>を 一つ増加 → ・
<変数>と <変数>と ・・ <変数>を 一つ減少 → ・
上のうち「クリア」だけは特別で、クリアできる対象は数値系変数に限らない。シーケンシャルファイルを除くあらゆるものをクリアできる(文字列変数、単純文字列実体、配列要素および全体、構造体要素および全体など・・)。
「セット」はフラグ(真理値を格納する)のような変数に 1(真の値)を設定するのに使うとよい。「クリア」と機能的には似ているが、整数変数にしか適用できない。
「一つ増加」「一つ減少」は変数の内容を1だけ増減する便利で高速な単語である。例えば、
カウンタを 一つ増加する
は、
カウンタに 1を 加え カウンタに 入れる
と等価である。前者のほうが見た目も直感的で分かりやすい。
さて、数値変数に限らないが、このような、変数に副作用を与える単語は、変数名に特定の送り仮名(助詞)が強要されるので注意する。
例えば「売り上げ」という変数があるとき、
売り上げ クリアする ←助詞がない!
売り上げに クリアする ←「に」?
は、一見して不自然な日本語に見えることから推察される通り、誤りである(コンパイラは文法エラーを検出する)。
例えば「クリア」では「を」が強要されるのだが、日本人であれば、特に意識しなくても正しい送り仮名を振っているはずなので、あまり神経質に考える必要はない。
つぎに、指定した値で変数の内容を更新する次の単語群がある。
構文=
<数値>を <変数>に 入れる → ・ (送り仮名は「へ」も可)
<数値>だけ <変数>を 増加する → ・
<数値>だけ <変数>を 減少する → ・
注:アンダーラインを引いた送り仮名は必須
上のうち「入れる」(代入)だけは特別で、代入先は変数に限らない。配列全体、構造体全体、ファイル(論理ファイル)など、あらゆるオブジェクトに代入できる(たとえばファイルをファイルに代入できる!)。
「増加」「減少」は、指定した値で変数の内容を増減する便利な単語である。
例えば、
10だけ カウンタを 増加する
は、
カウンタに 10を 加え カウンタに 入れる
と等価である。
1つの値を受け取り、1つの値を返すもの
このグループ以降はすべて、スタックからデータを受け取り、演算結果を再びスタックに返す。
このグループに属する処理単語は次のようなものである。
構文=
<数値>の 負数 → <数値>
A → -A
<数値>の 絶対値 → <数値>
A → |A|
<数値>の NOT → <数値>
A → Aの全ビット反転
<数値>の 一つ加え → <数値>
A → A+1
<数値>の 一つ引く → <数値>
A → A-1
<数値>の 二つ加え → <数値>
A → A+2
<数値>の 二つ引く → <数値>
A → A-2
以下はビット操作など上級者向けの処理単語なので初級者は読み飛ばして構わない
<数値>の 上位ワード → <数値> 12345678H → 00001234H
<数値>の 下位ワード → <数値> 12345678H → 00005678H
<数値>の 上位バイト → <数値> 12345678H → 00000056H
<数値>の 下位バイト → <数値> 12345678H → 00000078H
<数値>の 上下ワード交換 → <数値> 12345678H → 56781234H
<数値>の 上下バイト交換 → <数値> 12345678H → 12347856H
<数値>の 上下ニブル交換 → <数値> 12345678H → 12345687H
代表的な「負数」は次のように用いる。
Aの 負数をとる → -A
「NOT」は全ビットを反転する機能(1の補数をとる)である。
「一つ加え」「一つ引く」などの4種の単語は、1または2を加減算する専用の単語である。例えば、「一つ加え」は、
1を 加え
とまったく等価であるが、より高速であり、しかもプログラムを小さくできる。(注1)
注1
下記によって変数への副作用を期待してはいけない。
<変数>に 3を 加える
<変数>に 一つ加える
「加え」や「一つ加え」は、あくまで、スタックに積まれたデータに演算を施し、その結果を再びスタックに返す機能である。変数に副作用を与えるのならそれぞれ「増加」「一つ増加」を用いるべきである。言葉が似ているので使い分けに注意したい。
2つの値を受け取り、1つの値を返すもの
このグループに属する処理単語は次のようなものである。
構文=
<数値1>と <数値2>を 加え → <数値> → A+B
<数値1>から <数値2>を 引く → <数値> → A-B
<数値1>に <数値2>を 掛け → <数値> → A*B
<数値1>を <数値2>で 割る → <数値> → A/B
<数値1>を <数値2>で 割った余り→ <数値> → AmodB 注:「余り」も等価
<数値1>と <数値2>の 大きい方 → <数値> → AまたはB
<数値1>と <数値2>の 小さい方 → <数値> → AまたはB
<数値1>と <数値2>を AND → <数値> → A & B
<数値1>と <数値2>を OR → <数値> → A | B
<数値1>と <数値2>を XOR → <数値> → A xor B
<数値1>と <数値2>を 左シフト → <数値> → AをBだけ左シフト
<数値1>と <数値2>を 右シフト → <数値> → AをBだけ右シフト
代表的な「加える」のスタック仕様を示す。
Aと Bを 加える → A+B
「割る」「割った余り」および、後に説明する「商と余り」「余りと商」は内部で割り算が行われる。ゼロで割った場合、異常な処理が行われたとみなされ、次のようなメッセージが表示され、強制的にプログラムの実行が終了するようになっている。
エラー:ゼロで除算しました。
「AND」「OR」「XOR」は、32ビット整数の各ビットについて論理演算を行う。
Aと Bの ANDをとる → A&B
真理値(真か偽か)としてのAND/ORをおこないたい場合は、「かつ」「または」を用いること(第3章参照)。
「大きい方」「小さい方」は、次のように用いる。
Aと Bの 大きい方をとる → AまたはB
「左シフト」「右シフト」は、次のように用いる。
Aを <ビット数>だけ 左シフトする → シフトした結果
2つの値を受け取り、2つの値を返すもの
このグループに属するのは「商と余り」および「余りと商」である。次のように用いる。
構文=
<数値1>の <数値2>での 商と余りをとる → <商>、<余り>
<数値1>の <数値2>での 余りと商をとる → <余り>、<商>
上記2語は返される数値のスタック順が違うだけで本質的には同じことをしている。
余りがスタック手前に来たほうが良ければ前者を、商がスタック手前に来たほうが良ければ後者を使う。プログラム記述の都合で選んで欲しい。
2つの値を受け取り、検査結果を返すもの
このグループに属する属する処理単語は次のようなものである。
構文=
↓1または0
<数値1>と <数値2>が 等しい → <真/偽>
<数値1>と <数値2>が 異なる → <真/偽>
<数値1>が <数値2>より 大きい → <真/偽>
<数値1>が <数値2>より 小さい → <真/偽>
<数値1>が <数値2> 以上 → <真/偽>
<数値1>が <数値2> 以下 → <真/偽>
数値の比較は、符号付きの32ビット整数として行われる。また、演算結果を必ず1(真)か0(偽)として返すことが特徴である。
多くの場合、
Aと Bが 等しい
ならば ・・・・・・・・
つぎに
のように、条件分岐のために用いられることが多いが、本来は、条件分岐とはまったく独立した単なる演算単語であることを認識しておきたい。
次のプログラムをご覧頂きたい。
Aと Bが 等しい
ならば ステータスを セットし
さもなければ
ステータスを クリアし
つぎに
「等しい」が1または0を返す演算単語であることを利用すれば、上のプログラムは次のように簡単にできる。
Aと Bが 等しいをとり ステータスに 入れる
1つの値を受け取り、検査結果を返すもの
このグループには次のものがある。
構文=
↓1または0
<数値>が ゼロ? → <真/偽> 「0に 等しい」と等価
<数値>が ゼロ以外? → <真/偽> 「0と 異なる」と等価
<数値>が 正? → <真/偽> 「0 以上」と等価
<数値>が 負? → <真/偽> 「0より 小さい」等価
<数値>が 正の数? → <真/偽> 「0より 大きい」と等価
<数値>が 負の数? → <真/偽> 「負?」と等価
<真/偽>が 偽? → <真/偽> 「ゼロ?」と等価
「正?」と「正の数?」は名称が似ているが機能が異なるので注意したい。もともと「正?」は「負?」の逆判定(
"負ではない"意味なので0に対し真を返す)として設けたものだが、その名前からして「正?」が
"0より 大きい" と誤解されることが多く、教育用Mindの開発を契機に、より学校での数学の教えに近いものとして別途、「正の数?」(=0より大きい) と 「負の数?」(=0より小さい) を設置した経緯がある。
「偽?」は「ゼロ?」と等価な語であるが、その名称からして真偽値の演算に使うこと(真偽を逆にして返す機能)を想定している。
整数演算の同義語
日本語としての慣習から、次のような同義語が定義されている。
足す、和 <数値1>と <数値2>の 和が ‥ ←「加え」と等価
差 <数値1>と <数値2>の 差が ‥ ←「引く」と等価
積 <数値1>と <数値2>の 積が ‥ ←「掛け」と等価
商 <数値1>の <数値2>での 商が ‥ ←「割る」と等価
剰余 <数値1>の <数値2>での 剰余が ‥ ←「割った余り」あるいは「余り」と等価
以外、以外? <数値1>が <数値2> 以外 ‥ ←「異なる」と等価
また、同様の同義語であるが、次のものは、ゼロかそうでないかの判定を、本来の数値として見るよりは、真理値としてみるケースを想定して用意した単語群である。
偽? (例) <数値>が 偽? ‥ ←「ゼロ?」と等価
真? (例) <数値>が 真? ‥ ←「ゼロ以外」と等価
上記の「偽?」は否定処理として用いられる(真に対し偽を、偽に対し真を返すから)。
「真?」は次のような場面で用いると良いだろう。
成功検査し 真?
ならば 「おめでとう。」を 表示する
つぎに
上記では、「成功検査」という処理単語が、1(成功)または0(失敗)を返すことを想定している。このような場合、
成功検査し
ならば ・・・・・・・・
つぎに
では、言葉として不自然であるし(しかし動作上はまったく問題無い)、
成功検査したものが ゼロ以外
ならば ・・・・・・・・
つぎに
では、真理値を判定している気分にならない(結局、「成功検査」という名称自体が検査結果をスタックに返すことを暗示しないことが原因)。
いずれにしても、このようなケースで「真? ならば」とすることは、表現を自然にするのに相当効果がある(注2)。
注2
「真? ならば」の記述に対して、コンパイラは最適化により「真?」を無視するので、このような記述によって処理が冗長になることはない。同様に、「偽?ならば」に対して、コンパイラは「でなければ」の1語に置き換えるようになっており、これも冗長にはならない。
なお、
成功?
ならば ・・・・・・・・
つぎに
のように、単語名を変えてしまうのも1つの手である。「成功?」であれば、いきなり「ならば」で受けてもおかしくないだろう。
2つのデータを受け取り、しかも、そのデータの順番が意味を持つような処理単語を書いた場合、コンパイラによるデータの逆転介入が行われることを承知して欲しい。
例えば、
5から 2を 引く ‥‥‥��
と書く場合だが、このデータを逆に記述して、
2を 5から 引く ‥‥‥��
としても(日本語として同じ意味であるように)正常に演算が行われる。これは、コンパイラが、データの逆順記述をその助詞の使い方から自動判断し、2つのデータを逆転してから処理するというサービスを行うからである。
日本人はそのときの気分によって、�,鮟颪い燭雖△鮟颪い燭蠅垢襦�このようなものの一方だけを正しいものとし、他方を誤りとするのはプログラマの負担を増やすことになるので、Mindでは両方を許している。
さて、このサービスについて、次のことを承知しておく必要があるだろう。
まず、どういう順番が標準形かという点である。「5から 2を 引く」が標準形であるが、これは、
5−2
という、通常の数式表現をした場合のデータ順と同じものが標準形であると思えばよい。したがって、
2を 5から 引く ‥‥‥��
は、逆順だと考えることができる。
次に、このようなサービスが行われる単語はどのようなものかという点であるが、2つのデータの順序が意味をもつすべての数値演算が対象であると思えば良いだろう。次のような単語群である(例外は「商と余り」、「割った余り」である)。
逆転介入を行なう処理単語
(整数演算)
引く
割る
左シフト
右シフト
大きい
小さい
以上
以下
(小数演算)
f引く
f割る
f大きい
f小さい
f以上
f以下
「加える」や「掛ける」「AND」など、データ順を問わない(=逆にしても結果が同じ)演算語では、どのような助詞が記述されていても、このような逆転介入は行われない。
なお、2つのデータを受け取る処理単語であるにもかからわず、記述されているデータが1つの場合にもサービスは行われない。次のようなケースである。
余裕計算とは (数値 → 数値)
100から 引くこと。
上のプログラムは 〔100 − 数値〕 の計算を期待しているのだが、実際には 〔数値 − 100〕 が計算されてしまう(しかもコンパイラは何も言わない)。処理単語「引く」の左側に2つのデータが明に書かれていないので、逆転介入せずにありのまま処理がおこなわれる(スタックに詰まれている値から100が引かれる)。
最後に、このサービスを受けるための助詞の使い方について触れておく。数多くの助詞が挙げられているが、これらは参考資料として考え、あまりこだわらないで欲しい。
なぜなら、ほぼ確実に、日本語として正しい助詞を使えばサービスを受けられるようになっているからである。
コンパイラはまず、助詞を次のようにグループ分けする。
表6-1 コンパイル時の助詞の優先値
| 優先値 |
助詞 |
| 1 |
が、 は |
| 2 |
から、 より |
| 3 |
を |
| 4 |
よりも、 で、 だけ、 による、 により、 での、 との |
| 5 |
に、 へ、 と |
2つのデータの助詞を次のように表したたとき、次の条件を満足した場合に逆転介入を行うようになっている。
データ1+助詞1 データ2+助詞2 [処理単語] → ?
↓
以下の条件を満たした時に逆転介入をおこなう
助詞1の優先値 > 助詞2の優先値
たとえば、次はいずれも介入を受ける例である。
2を 5から 引く 優先値:3 > 優先値:2 であるため逆転介入
2で 10を 割る 優先値:4 > 優先値:3 であるため逆転介入
10より 2が 小さい 優先値:2 > 優先値:1 であるため逆転介入
注3
逆転介入をおこなう処理単語は、その定義時に特殊な属性を付与する記述を行なう必要があるが、それについては上級編にて解説する。
前項で解説したのは、2つのデータをスタックで渡すような処理単語における逆転介入であったが、これと似たもので、[データ] と [必須変数] を必要とする次のような記述に対しても介入が行われる(おおむね変数に副作用を与えるような単語である)。
構文=
<数値> <変数名>(送り) [処理単語] → ?
↑強制される送り仮名
「入れる」を例にとって説明しよう。
(正順) 100円を 売り上げに 入れる
(逆順) 売り上げに 100円を 入れる
(正順) 100円だけ 売り上げを 増加する
(逆順) 売り上げを 100円だけ 増加する
上の(逆順)のケースでは、数値と変数を逆に記述しているが意図は正順と同じで、実行時の効果も正順で書いたものと同じになる。
どのようなものが正順(標準形)か‥であるが、データが左から右に(文章を読むのと同じ方向に)向かって流れるような記述、あるいは、副作用を受ける変数が処理単語の直前に書かれているものが正順である。
逆順にしたからといって、実行速度が落ちたりオブジェクト生成が冗長になったりはしないから、正逆にこだわる必要はない。
また、数値演算以外にも、文字列操作やファイルのアクセスなど、処理単語の直前にデータと変数名(あるいは論得ファイル)の記述が強要されるあらゆる場面で逆転介入を受けることでできる。
処理単語の例を挙げておく。
データと必須変数の逆転介入を行なう処理単語
(代入)
入れる
(数値演算)
増加、 減少、・・ など
(文字列操作)
検索、 切り出し、 削除、・・ など
(ファイルアクセス)
オープン、一文字書き込み、 書き込み、・・ など
数学で使うような数式や、他のプログラム言語での代入文に相当する記述ができる。例えば、
個数に 単価を 掛け 売り上げに 入れる
というMind流の記述は、もちろんこのように書いてまったく正しいのだが、別の表記である「数式表現」を使うことで次のように書くこともできる。
構文1=
数式表現で代入までおこなう場合
(形式) [<変数名> := <・・・式・・・>]
(例) [売り上げ := 単価 × 個数]
記号 [ : = ] は全角・半角のどちらも可。例えば ':=' は ':=' でも良い。
構文2=
数式表現で計算だけをおこなう場合
(形式) [<・・・式・・・>]
(例) [単価 × 個数]を 売り上げに 入れる
(例) [単価 × 個数]が 1000円 以上
ならば ・・・・
つぎに
(例) [(単価 × 個数) ≧ 1000円]
ならば ・・・・
つぎに
[ ]の中では演算だけをおこない、結果がスタックに積まれる
- 注
- ここでは整数のケースのみ解説しているが、小数の数式表現については こちら を参照して欲しい。
式の中で使える演算子は次の通り(全角/半角どちらでも可)。
(代入)
:=
−以下は優先度低い−
(加減算)
+
−
(比較)
=
≠ (または <>)
<
≦ (または <=)
>
≧ (または >=)
−以下は優先度高い−
(乗除算)
× (または *)
÷ (または /)
% (または mod)
演算の優先順位は一般的なプログラム言語と異なり2レベルのみである。加減算および比較のグループ(優先度低い)とその他(優先度高い)である。細かな優先を扱いたい場合には 丸括弧( )を使う。
数式表現で使われる 角括弧[ ]と 丸括弧( )について補足しておく。
Mindのプログラム中の単語は、第2章「単語名と分かち書き」で述べたように単語と単語の間に空白を入れることで分かち書きする必要があるが、角括弧[ ]、 丸括弧( )、 句点 。 の3種は例外的に 密着して記述できる。たとえば以下のような表記である(密着の様子が分かりやすいので半角で書いているが全角でも同様である)。
[(個数 * 単価) / 2]を ←ここまでは密着して良い(しかし * と / の両側は空ける)
数式表現の中で引用できる単語の種類は以下の通りである。
数式表現の中で引用できる単語
数値定数: (例) 123
数値定数のシンボル定義:(例) 最低販売価格は 数値 3400。 ‥としたときの「最低販売価格」
数値変数: (例) 売り上げは 変数。 ‥としたときの「売り上げ」
処理単語:(下記注) (例) 売り上げ取得とは ・・・・・。 ‥としたときの「売り上げ取得」
関数: (例) 売り上げ取得とは 関数 ・・。 ‥としたときの「売り上げ取得」
注:処理単語で使えるものはデータを受け取らずに数値を1つ返すタイプだけである
逆に、以下は数式表現中では引用できない例である。
数式表現の中で引用できない単語
文字列定数: (例) 「あいう」
文字列定数のシンボル定義:(例) 名前は 文字列定数 「山田」。‥としたときの「名前」
文字列変数: (例) 名前は 文字列(実体)。 ‥としたときの「名前」
型紙参照の構造体、 :(例) ○○は 構造体 △△型。 ‥としたときの型紙要素
データを受け取る処理単語:(例) 「加え」「減少」
文字列を返す処理単語 :(例) 住所参照とは ・・。 ‥としたときの「住所参照」
文字列を操作する処理単語:(例) 「左端文字」「一文字切り出し」
ファイル操作する処理単語:(例) 「一行読み出し」
この項では小数を処理する方法を解説する。
変数への格納および演算すべて64ビット長の浮動少数形式で行われる。
Mindで言うところの '小数' は他のプログラミング言語で '倍精度浮動小数' と呼ばれるもので、型宣言は他の言語の多くの場合'double'と表記されるものに相当する。
小数の定数としての表記
第2章「プログラム表記の基本」と重複するが改めて解説する。
小数の定数は以下の例のように表記する。
- 3.14
- ‥ 小数だけの形式
- 1.23E2
- ‥ 指数部を持つ形式
- -1.23E-2
- ‥ 指数形式で、仮数部と指数部が共に負の場合
- −1.23E−2
- ‥ 数字・記号は全角でも良い('E'は小文字'e'でも可)
小数が扱える範囲は仮数部で15桁、指数部が+-308である。
Mindでは小数の仮数部の有効桁が整数のそれより長いので、裏技的ではあるが、小数形式を精度の高い整数演算として使うこともできる。
小数の値を単語名(シンボル)として定義することもできる。
構文=
<単語名>は 小数定数 <小数値>。 ←単なる数値を単語として定義
<単語名>は 小数定数 <Mind式>。 ←式を評価した結果の数値を単語として定義
─── Mind式に使える演算語 ───
f加え、 f引く、 f掛け、 f割る、 f割った余り
f等しい、 f異なる、 f大きい、 f小さい、 f以上、 f以下
たとえば、
(例)
補正乗率は 小数定数 1.35。
のように定義すれば、以後のプログラム中にこの単語(補正乗率)が現れたとき、そこに「1.35」という数値が書かれているのと同じ扱いを受けるようになる。
もし、プログラムの中に(補正乗率の意味で)「1.35」という数字がたくさん表記されているような場合、この方法を使えば1.35という具体的な値の表記を1箇所に集中させることができる。将来、値を変更するような場合に、1箇所を訂正するだけで済むという利点のほか、プログラム中に単に「1.35」と書かれているよりも、「補正乗率」と書かれているほうがプログラムの意図がよく分かるという利点もあるので積極的に利用したい。
構文説明の後半にある<Mind式>を使った例を以下に示す。
(例1)
第一補正乗率は 小数定数 1.35。
第二補正乗率は 小数定数 第一補正乗率に 1.5を f掛けたもの。
上記2行目では「小数定数」の右辺で数値の演算(Mind流の演算式)を記述しているが、このような表記も受け付ける。上記例は以下のように定義したのと同じになる。
(例2)
第一補正乗率は 小数定数 1.35。
第二補正乗率は 小数定数 2.025。
例1のような表記にすることで実行速度が落ちたり、メモリを余計に消費するようなことはない。ソースプログラムは多少長くなるものの、ここでの演算はコンパイル時におこなわれるため実行時間やメモリ消費にはまったく影響を与えない。
定義済みの小数の定数
小数の定数に名前を付けたものとして、たとえば「π」などが標準で定義されている。以下の通り。
(注:以下では単語名に半角を使っているが全角でも可)
(注:頭にfが付いたものは、付けないと数字から始まる
単語となって直接の数値表記と解釈されてしまうことを防ぐため)
f0.0 ←定数 0.0 のこと
f1.0 ←定数 1.0 のこと
e ←自然対数の底
log10_e ←eの常用対数を値とする定数
log_2 ←2の自然対数を値とする定数
log_10 ←10の自然対数を値とする定数
π ←円周率 パイ
π/2
π/4
f1/π
f2/π
√2
(πをPIとして表記する以下も利用可能)
PI
PI/2
PI/4
f1/PI
f2/PI
3つの値を受け取り、1つの値を返すもの
このグループに属する処理単語は「範囲?」だけである。
構文=
<数値1>が <数値1>から <数値2>の 範囲? → <真偽>
小数変数に副作用を与えるもの
小数変数に値を代入したり更新を行う単語群を示す。
以下の解説では通常の変数としての例を示すが、実際には配列・構造体・型紙の要素となる変数にも適用できる。
まず以下のものは変数のみを指定、あるいは値と変数のペアを指定し、変数に副作用を与えるものである。
構文=
<小数値>を <小数変数>に 入れる → ・ (送り仮名は「へ」も可)
<小数変数>を クリア → ・ (0を代入すること)
<小数値>だけ <小数変数>を 増加する → ・
<小数値>だけ <小数変数>を 減少する → ・
注:アンダーラインを引いた送り仮名は必須
「増加」「減少」は、指定した値で変数の内容を増減する便利な単語である。
例えば、
1.2だけ 積算値を 増加する
は、
積算値に 1.2を f加え 積算値に 入れる
と等価である。
数式表現中の小数扱い
既に本章の
「数式表現」 の項で整数の数式表現について解説した。数式中での表記は基本的に整数の場合と同じである。改めてまとめるが基本となる構文は以下の2通りである。
構文=
(形式1) [<変数名> := <・・・式・・・>]
(形式2) [<・・・式・・・>]
記号 [ : = ] は全角・半角のどちらも可。例えば ':=' は ':=' でも良い。
上記で示す <・・・式・・・> (以下では単に式と書く)の中で使える演算語についての補足を以下にまとめた。
- 四則演算など 整数の数式表現で解説した演算語 はすべて小数でも使える
- 原則的に、演算語に与える値が小数なら小数の演算語が使われ、結果も小数である
- 比較演算(>、=など)では、与える値にかかわらず結果は整数である
- 関数の呼び出しでは、その関数を宣言したときの型により整数が返されたり小数が返されたりする
混合演算(整数と小数がまざった使い方)は以下のように扱われる。
- 演算語に与える数値のうち少なくとも1つが小数であれば、整数値は自動的に小数に変換され小数で演算が行われ、結果もまた小数である。
- 変数への代入を記述している場合で、式の結果の型と代入先変数の型が異なる場合、式の結果は代入先に合わせて型変換が行われる。
小数の演算を行う処理単語
小数の計算は前記した数式表現で使うことが多いと思われるが、Mind流の通常表現の中でもおこなえる。
Mind流表記で注意するのは、たとえば加算では「
加え」ではなく「
f加え」を使うなど、小数向けの処理単語を明に使う必要がある点である。(実は数式表現であっても内部的には、たとえば「+」の表記で「f加え」が呼び出されている)
まず、四則演算として以下の処理単語が用意されている。
構文=
<小数1>と <小数2>を f加え → <小数> → A+B
<小数1>から <小数2>を f引く → <小数> → A-B
<小数1>に <小数2>を f掛け → <小数> → A*B
<小数1>を <小数2>で f割る → <小数> → A/B
<小数1>の <小数2>での f割った余り→ <小数> → AmodB
<整数1>を <整数2>で 小数まで割り → <小数> → A/B(小数)
上記表の末尾にある「小数まで割り」は特殊な機能で、整数値を受け取るが、商として小数値を返す。たとえば、
1を 3で 割り
は普通の整数演算で結果はゼロになるが、
1を 3で 小数まで割り
は小数で割り算が行われるので、結果は 0.3333... となる。
ちなみに、
3を 1で 小数まで割り
は割り切れるが結果は小数(3.0)である。
次に、比較演算として以下が使える。小数を与えるが、結果は整数なので注意したい。
構文=
↓整数の1または0
<小数1>と <小数2>が f等しい → <真/偽>
<小数1>と <小数2>が f異なる → <真/偽>
<小数1>が <小数2>より f大きい → <真/偽>
<小数1>が <小数2>より f小さい → <真/偽>
<小数1>が <小数2> f以上 → <真/偽>
<小数1>が <小数2> f以下 → <真/偽>
整数と小数の型変換
整数を小数に、あるいはその逆に変換する処理単語を解説する。
構文=
<小数値>を 整数化 → <整数値>
<整数値>を 小数化 → <小数値>
初等関数
以下の三角関数、対数、指数などが利用できる。
acos(x) ←逆余弦(arc cosine)
asin(x) ←逆正弦(arc sine)
atan(x) ←逆正接(arc tangent)
cos(x) ←余弦(cosine)
sin(x) ←正弦(sine)
tan(x) ←正接(tangent)
cosh(x) ←双曲線余弦(hyperbolic cosine)
sinh(x) ←双曲線正弦(hyperbolic sine)
tanh(x) ←双曲線正接(hyperbolic tangent)
exp(x) ←指数関数(eのx乗)
log(x) ←対数関数(eを底とする自然対数)
log10(x) ←対数関数(10を底とする常用対数)
pow(x,y) ←べき乗(xのy乗)
sqrt(x) ←平方根
fabs(x) ←絶対値
radian(x) ←角度 x(度単位)をラジアンに変換
degree(x) ←角度 x(ラジアン単位)を度単位に変換
なお、関数本来の表記(func(X))のほか、Mind流の通常表現(X のfuncを ・・)も(変則的ではあるが)可能である。
(例)
radian(30.0)を ・・・
30.0の radianをとり ・・・
上記2つは同じ動作をする。
小数を扱う処理単語の定義
整数を扱う処理単語の解説として、第2章「プログラム表記の基本」の中の項「処理単語の属性を指定」にて既に解説しているので合わせて読んで欲しい。
処理単語の属性指定の構文を改めて示す。
構文=
<処理単語名>とは 処理単語 <属性> <属性> ・・ <属性>
・・・・・し ↑下線部は途中で改行してはならない
・・・・・すること。
─── 属性に記述できる語 ───
整数入力、 小数入力 | 整数出力、 小数出力
逆転抑制
(その他細かなものについては上級編に)
上記を補足する。
まず、定義する処理単語が小数値を返すものであれば「○○は 処理単語 小数出力」のように定義を始めることを薦める。これにより、たとえば数式表現中でその処理単語を引用した場合に、その処理単語がスタックに小数を返すものであることが明確になり、コンパイラは適切な対応を取れるようになる。
さらに、その処理単語が小数値を受け取る場合、属性に「小数入力」を記述することで、上位側で処理単語を引用する際、その処理単語名の直前に書いたデータの型検査が行われるようになる。「小数入力」の記載は必須ではないものの、そのような検査を受けられるというメリットがある。
小数を扱う関数の定義
整数向けのときと同様に小数を扱う関数を定義できる。
関数の定義については(整数扱いの関数として)第2章「プログラム表記の基本」の中の項「関数」にて既に解説しているので合わせて読んで欲しい。
関数を定義する構文を改めて示す。
構文=
<関数名>とは 関数 <入力型> ・・ <入力型> <出力型>
・・・・・し ↑下線部は途中で改行してはならない
・・・・・すること。
注:「関数」から末尾の<出力型>までを1行で表記すること
注:「入力型」は1個〜3個を書く。この個数が関数の引数個数となる
注:「入力型」が複数ある場合、すべて同一型であること
注:「入力型」が書かれない場合は1つの整数入力とみなされる
注:「出力型」が書かれない場合は整数出力とみなされる
─── データ型に記述できる語 ───
整数入力、 小数入力 | 整数出力、 小数出力
例として以下の仕様の関数を定義してみる。
xの2乗とyの2乗を加えてその平方根を返す関数
hypot1とは 関数 小数入力 小数入力 小数出力
Xは 小数
Yは 小数
Xと Yに 入れ
[SQRT(POW(X,2.0) + POW(Y,2.0))]を 返すこと。
(呼び出し例)
メインとは
hypot1(3.0, 5.0)を 5桁で 小数形式で表示し 改行すること。
この課題の解答としては、上記以外にも次のようにさまざまな定義方法がある。
数式表現を使わずSQRT関数の引数だけで演算する (引数の中で数式を書ける)
hypot2とは 関数 小数入力 小数入力 小数出力
Xは 小数
Yは 小数
Xと Yに 入れ
SQRT( POW(X,2.0) + POW(Y,2.0) )を 返すこと。
加算と平方根をMind流表記とする (関数はMind流に呼び出すこともできる)
hypot3とは 関数 小数入力 小数入力 小数出力
Xは 小数
Yは 小数
Xと Yに 入れ
POW(X,2.0)と POW(Y,2.0)を f加え SQRTをとる。