スタックとは


HP電卓ではRPNを実現するためにスタックというメモリーを使います。HP電卓初心者にとっては、これがひとつの難関です。つまりどんな簡単な計算でもスタックを使うので、スタックの動きに慣れるまでは「本当にこの計算結果は正しいのか?」と不安になったり、不必要にレジスタを多用したりしてややこしい操作をしてしまうのです。

スタックは計算機内部にあって、その扱いは電卓が自動的に行っています。操作する人(つまり私たち)に求められるのは、計算機がスタックをどう使っているか、スタックの内容が今どうなっているかを把握することです。ただし、普通に計算しているときはそれほど意識する必要もないと思います。わかっていると、ややこしい計算をより簡単な操作で結果が求められる、くらいに考えてください。

HP電卓のスタックは、X、Y、Z、Tという4つの「箱」が縦に積まれていると想像してください。下からX、Y、Z、Tです。電卓の表示画面には、常にXというスタックの内容が表示されています

T0
Z0
Y0
X1

それでは、『 1 + 2 』 を計算するときのスタックの動きを見てみます。
HP電卓では key key key と入力します。まず key をキーインすると、Xスタックに「1」が入ります。表示は「1」です。

T0
Z0
Y1
X2

次に key を押してから、 key をキーインします。key はふたつの数値の区切りのためです。そうでないとRPNでは「1」と「2」だか「12」だかわからないからです。
すると上のYスタックに「1」が上がり、Xスタックに「2」が入ります。表示が「2」になりました。

T0
Z0
Y0
X3

次に key を押すと、計算機はXスタックの内容にYスタックの内容を足して、結果をXスタックに格納し、Yスタックをカラ(=0)にします。「3」が表示されています。このようにHP電卓ではスタックを使って演算をおこなっていきます。

これはスタックの動きの基本を説明するためのもので、実用的には意味のないことです。こんな計算ではスタックを意識する必要は全くありません。


もう一つ、なぜHP電卓ではカッコが要らないのか説明します。

先程の (1+2) x (3+4)という計算をやってみます。RPNでは「 1 2 + 3 4 + x 」と記述します。HP電卓ではふたつの数字の区切りにENTERを入力します。

実際のキーインはこうなります。

key key key key key key key key key

スタックの動きを見てみましょう。

T0
Z0
Y1
X2

key key key で、Xスタックに2が、Yスタック1が入りました。

T0
Z0
Y0
X3

key でXとYが足され、結果がXに残ります。

T0
Z3
Y3
X4

そのまま続けて key key key とキーインすると、スタック内部はこうなります。
つまり先程の計算結果"3"はZスタックまで自動的に上昇し、XとYに新しい数値が入ります。

T0
Z0
Y3
X7

key でXとYが足され、結果がXに残ります。先程の"3"は自動的にYスタックに降りてきます

T0
Z0
Y0
X21

key でXとYが掛けられ、結果がXに残ります。スタックの自動上昇・下降のおかげで、カッコが要らないのです

簡単な例でしたが、スタックの動きがわかっていただけたでしょうか。このスタックのおかげで、どんなに複雑な計算でもカッコを使わずに答えが出せるわけです。
ちなみにこれはHP電卓のマニュアルに載っている例題ですが

form

こんな計算でもHP電卓ならメモリー(M+, M-, MR)など使うこともなく、式を見て計算順序のとおりにキーを押していくと答えが出てきます。”普通の電卓”ではどうやって計算していたのか、最近使ってないので思い出せませんが。


Tスタック

一番上のTスタックはカラにならない特殊なスタックで、同じ数を何度も足したり掛けたりする場合に便利なスタックです。つまり

T2
Z2
Y2
X2

key key key key ですべてのスタックに2が入ります。

T2
Z2
Y2
X4

ここで key を押すとXとYが掛けられて答えの"4"がXに残ります。YとZは自動的に下降しますが、Tは自身をZにコピーするだけで、カラになりません

T2
Z2
Y2
X8

ですから後は key を押すだけで、無限に(オーバーフローするまで)定数の掛け算ができます。

Tスタックをカラにするには、key key key key とスタックすべてに 0 を入れてやります。


『数式どおり』は本当に数式どおりか?

これらのスタックの動きやキー・インの方法を「面白い」と感じた方には、HP電卓をお薦めします。逆に「やはりややこしい、数式どおりのほうがわかりやすい」(おおかたの人の反応です)という人にはHP電卓を薦める気はありません。そもそも私のこんな拙劣な説明で理解してもらえるとは思っていませんし。

しかし回路設計や機構設計など常に複雑な計算が必要で、現状の電卓に「こんなものなのかな」と感じているのであれば、HP電卓は一考の価値があります。

確かに「数式どおりにキーインすれば結果が出る」というメリットは誰にもわかり易いと思われます。しかし実は、数式どおりにキーインできるのはけっこう単純な計算だけなのです。「こんなものなのか」という感じは、そこからきていませんか?

■またまた単純な例を引き合いに出しますが、一般の式で表わす「1 + SIN(30) = 」という計算は、"普通の"電卓ではどう計算しますか?

HP電卓では

と押します。馴れた人なら

と押すでしょう(これならENTERは不要です)。

"普通の"電卓では、「30 SIN + 1 = 」でしょうか? おやおや、よく似ていますね。こんな簡単なものでもとても数式どおりとはいえません。本来の”数式通り”なら、「 1 + SIN 30 =」でしょうが、こうキーインできる電卓は”よほど”特殊な電卓でしょう。

どうしてこの式が数式通りにキーインできないかというのは、プログラムを書く人なら想像はつくと思います。つまり計算機内部で、SINという関数を計算するためのルーチンに飛ぶ前に、引き数である「30」を得ておかなければならないためでしょう。強引に数式通りにキーインさせることももちろんできるでしょうが、そこまでして内部のソフトウエアを複雑にしても計算速度が遅くなるだけで大したメリットはない。これくらいは人間がやってくれということでしょう。

そのため一般の電卓では「四則演算は数式通り、関数計算はRPNもどき」という変則的な操作が必要になっているのです。これはある意味では操作する人にかかる負担だと思うのですが、「これが当たり前」と思って何も感じない人が多いのも事実です。複雑な計算になればなるほど、こうした電卓のルールに振り回されていないでしょうか?

一方、HP電卓がスタックを表にだしているのは、「どんな数学機能でも同じように操作できるようにするため」です。計算式によって関数キーや演算子キーを先に押したり後に押したりということがないのです。逆に言えば簡単な計算にもスタックを使うので初心者にはとっつきにくくなっていますが、簡単な計算だからこそ慣れるのも早いのです。そして慣れてしまうとこれほど効率的な電卓はないといえます。一度HP電卓を使い始めるともう手放せない、というのはそうした理由だと思います。

HP以外の電卓でも、あるいはパソコンでも、内部で動いているプログラムはスタックを頻繁に使っています。通常はそれを操作する人に意識させないのですが、HP電卓ではあえてそれを使う人間に意識させることによって、複雑な計算をより簡単におこなえるようにしているわけです。これも使う人間に負担をかけていることにはなるわけですが、それによってもたらされる結果(操作手順の簡単さ)を考えるとどちらが大きな負担でしょうか? HP電卓の場合はすぐに慣れてしまいますし。

■HP電卓がスタックを使う規則はふたつ。しかも単純です。
1.関数が必要としている入力(引き数)を、関数を実行する前にスタックに入れておくこと。
2.関数の結果はスタックに残り、それを次の関数の引き数にも使えること。

( 1 + 2 ) x 4 という式を計算してみます。

HP電卓では

とキーインします。

で、「+」が必要としているふたつの引き数を、先にスタックに入れます(規則1)。Xスタックに「2」、Yスタックに「1」が入りました。

を押した時点で、計算の結果「3」がXスタックに残ります。それをそのまま次の演算子「x(かける)」の引き数のひとつとして使います規則2)。

もうひとつの引き数 をキーインすると「3」がYスタックにあがり、「4」がXスタックに入ります。 をキーインするとXスタックとYスタックの中身が掛算されます。

答えがXスタックに残り、それが表示されます。

これが基本で、全ての計算はこの規則に則っています。


☆☆☆ちょっと横道☆☆☆ プログラム言語 FORTH

FORTH(フォース)というプログラム言語があります。Charles H.Moore という人が作ったものですが、これが一風変わった言語なのです。

FORTHはスタック言語と呼ばれるように、スタックを使ってプログラムを実行していきます。さらに効率的にスタックを使うために、RPNで記述します。つまりHP電卓と同じような感覚でプログラムが書けるわけです。

たとえば、FORTH インタープリターで 1 + 2 を計算するときは、1 2 + CR(RETURN)と入力します(数値や演算子の間はスペースです)。答えの 3 は一番トップのスタック(TOS)に残っているので、.CR と入力すると 3 を返します。「」は「TOSの値を表示せよ」という命令語です(BASIC言語の PRINT のようなもの)。

FORTH では更に「自己増殖」といって、今ある命令語(FORTHではワードと呼びます)を組み合わせて新しいワードを作っていきます。FORTH本体(カーネル)は数十の命令しかありません。逆に言えば、ワードを定義することがプログラミングであるといえます。

たとえば DUP (Duplicate)というワードはスタックのトップを2段目にコピーします。そこで、スタックの数値を2乗して表示するワード SQUARE を定義してみましょう。

: SQUARE DUP * . ;

これだけ。はじめのは定義であることを、は終わりであることをあらわす(立派な)ワードです。これは「SQUAREとは、トップ・スタックを2段目のスタックにDUPし、それらを掛けて(*)、トップ・スタックを表示()すること」という定義です。

これで SQUARE というワードが定義されたので、すぐに使うことができます。 5 SQUARE CR と入力すると、5を2段目にコピーし、ふたつを掛けて25をトップ・スタックに入れ、それを表示します。

どんなに複雑な動作をさせるワードであっても、たどっていくと数行のワードの組み合わせに行きつきます。この階層構造が FORTH のデバッグを容易にしています。

定義されたワードはボキャブラリに登録され、ボキャブラリが集まってディクショナリ(いわゆるライブラリ)を形成します。ディクショナリに登録しておけば、あとはいつでも呼び出して使うことができます。

FORTHを作ったMoore という人は天文台に勤めていて、コンピューターで望遠鏡を操作するのに適した言語はないかと探した揚げ句に、自分で作ってしまったということです。
FORTHなら、10 west 25 up 40 zoom+ ・・・(10°西へ、25°上に、40パーセントズーム・・・)のような記述が可能です。何をどうさせたいのかということが、プログラムを見るだけでよくわかります。制御用として FORTH が根強い人気がある理由がわかります。

私は一時期、FORTHで制御用のプログラムを書いていたことがあって、その前からHP電卓を使っていたのであまり違和感は無かったのですが、それでもアセンブラ表記まで
b a mov ・・・ 普通のアセンブラでは mov a b
とか
hl pop ・・・ 同じく pop hl
などとRPNで記述するので、最初のうちは戸惑った覚えがあります。でもこれも「b に a を mov しろ」「hl を pop しろ」と、実に日本語的な表記法なのです。

FORTHのワードは日本語の名前をつけることもできます。ということは、やろうと思えばすべてを日本語で定義することも可能です。しかも表現が日本語的なので違和感があまりありません。これを実際にやってしまった『MIND』というプログラミング言語がありました(懐かし〜)。基本はFORTHなのですが、これで書いたプログラムは日本語そのものにみえます。

「1に 2を たして 3に 4を たして かける」
「画面をクリアし ベルを鳴らす」

こういうプログラムが書けるわけです。

ワードの定義にしても先程のSQUAREのように

「2乗とは、トップ・スタックをDUPし、それらを掛けて、トップ・スタックを表示すること」

のように定義文が書けてしまうわけです。FORTH というのはまったく不思議な言語です。

HP電卓にしてもFORTHにしても、我ながら変わったものが好きだと思います(^_^;)


このページのトップへ 扉へ プログラミング