HOME > 電算 > hp 50g メモ

hp 50g メモ

雑感

hp 50g は数式処理システムを備えたグラフィカル電卓。RPL という言語を対話的に、あるいはあらかじめプログラムを書いて使うことができる。RPL は、スタックを利用する手続き型の言語で、名前やプログラムまで含めてオブジェクトである。もちろん、RPL のコマンドに対してさまざまなキーバインディングが定義されているので、電卓として気軽に使うことができる。

目次

再起動&メモリクリア

RPL 言語

ディレクトリ

数式エディタ(EQW: Equation Writer)

再起動&メモリクリア

[ON]+[F3] を同時に押して再起動(warmstart)。(「同時に押す」というのは、[ON] を押下した状態で [F3] を押し、[F3] から指を離してから [ON] から指を離すということ。このページでは、こうしたキー操作を [ ]+[ ]のように示し、たんなる[ ][ ]は、独立したキー操作の連続を示すことにする。)

すべてのメモリをクリアするには、[ON]+[F1]+[F6](同時に押す)。ビープ音のあと "Try to Recover Memory?" と尋ねられる。

RPL 言語

hp50g で、逐次キーをたたいてごく普通にスタックを使って計算しているようなときでも、これは RPL 言語を対話的に使っているに過ぎない。RPL では何でもかんでもオブジェクトである。特に、名前もオブジェクトであるし、プログラムもオブジェクトである。RPL のプログラムは、基本的にオブジェクトを並べたものを《 》でくくればできる。プログラムの中身は、手動でスタックを使った操作をする場合とほとんど同じでよい。

RPL は、オブジェクトをタイプして [ENTER] キーを打つか、プログラム内にオブジェクトを羅列し、先頭からインタープリタによって読み込ませることによって実行される。以下、このことをオブジェクトを「入力する」と表現する。入力されたオブジェクトは、そのままスタックに積まれたり、評価されたりする。入力されたときに何が起こるのかはオブジェクトの種類によって決まっている。早見表

Wikipedia によると、RPL は ROM-based procedural language の意味だそうである。参考にしたのは、電卓についてきた CD に入っていた pdf ファイル "HP 50g / 49g+ / 48gII graphing calculator--advanced user's reference manual" (以下 reference manual)。

1 [ENTER] をタイプするとスタックに 1 が積まれる。プログラムオブジェクトである 《 1 》 を [EVAL] してもスタックに 1 が積まれる。整数のほかに、実数や複素数や、その他いろいろ、入力するとただ積まれるだけの仲間がある。

数は EVAL しても自分自身になるだけである。

コマンド

コマンド・オブジェクトは入力されると、すぐさま実行される。たとえば + コマンドは、実行されるとスタックから 2 つの引数を消費し、その和をスタックに積む。+ コマンドオブジェクト自体はスタックに残らない。

代数オブジェクト(algebraic object)

この電卓で algebraic と言ったときには、われわれの見なれた記法で書かれた数式オブジェクトを指す。たとえば、1+2 などというのは algebraic な表現。クオートしないとスタックに積むことができない。クオートした algebraic を入力すると、そのままスタックに積まれる。したがって、'1+2' [ENTER] は、スタックに '1+2' を積む。

'1+2' という algegraic は [EVAL] すると 3 になる。この場合の + のように、代数オブジェクト中で使うコマンドを、とくに関数と呼ぶ。

名前

名前はオブジェクトである。名前にはローカルな名前とグローバルな名前がある。ローカルな名前とは、プログラム中で仮引数になった名前だけである。

名前は任意のオブジェクトを指すことができる。

1 'X' STO とタイプすると、グローバルな名前 X が 1 を指すようにする。なお、STO はコマンドである。リファレンスマニュアルは、このことき、名前のほうを variable と言い、それがオブジェクトを指し示すことを vaiable が オブジェクトを contain すると言う。

グローバルな名前の場合、名前がオブジェクトを指すという関係は、その関係を定義したときにいたディレクトリと、そのサブディレクトリにいるときだけ有効である。この関係はサブディレクトリ中で上書きできる。

次は、プログラム中でローカルな名前 X, Y を使っている例。

《→ X Y 《X Y +》》

このプログラムは、スタックから 2 つを引数として消費し、その和をスタックに積む。

プログラムを入力するとそれはたんにスタックに積まれるのが原則であるが、こうした構造の中にある内側のプログラムは、スタックに積まれるのではなく実行される点に注意。(もし《《1 2 +》》というプログラムを実行すると、《1 2 +》というプログラムが実行されずにスタックに積まれる)

ローカルな名前の場合、名前とそれが指すオブジェクトの関係はプログラムの中に限定される。プログラムが終了すれば、ローカルな名前は消滅する。

この《→ ローカルな名前 [ローカルな名前]... 《プログラム》》という枠組をリファレンス・マニュアルは「構造」と呼んでいる。同様に、《→ ローカルな名前 [ローカルな名前]... '代数表現'》という枠組みもあり、これも「構造」と呼ばれる。こちらは、'代数表現'が評価された結果がスタックに積まれる。(「構造」にはもう一種類あって、それは IF, THEN ... のようなものによって作り出される)。

グローバルな名前であろうとローカルな名前であろうと、クオートされた名前を入力すると、名前じたいがスタックに積まれる。これは、スタックを表示しているとき、液晶に 'X' と表示される。

グローバルな名前じたいを EVAL すると、
(I) その名前が他のオブジェクトを指していないならば名前じたいがスタックに積まれる。
(II) もし他のオブジェクトを指しているならば、名前が指す対象となっているるオブジェクトの種類によって、挙動が異なる。
(II-1)名前がプログラムオブジェクトを指しているなら、プログラムが実行される(これに対して、プログラムじたいを入力した場合、それはたんにスタックに積まれる)。
(II-2)名前がディレクトリを指しているならそのディレクトリがカレント・ディレクトリになる。
(II-3)名前が別の名前をさしているなら、その別の名前が EVAL される※。
(II-4)その他の場合は、名前が指すオブジェクトがそのままスタックに積まれる。

(※例:もし名前1 が名前2を指し、名前2が名前3を指し、名前3が何も指さないようなっているとき、名前1を EVAL すると名前3がスタックに積まれる。)

クオートされていないグローバルな名前を入力すると、EVAL される。次はこのことを確かめるプログラム。

《1 'X' STO 
X 'Y' STO 
2 'X' STO 
Y》

このプログラムを実行すると、はじめに 1←X から Y→1←X になり、次に 1←Y 2←X になる。2 行目の X はスタックに積まれずに評価されるので STO が受け取るのは 1 である。このプログラムを評価するとスタックの最上部には、最後の Y を評価した結果である 1 が積まれる。

《1 'X' STO 
'X' 'Y' STO
2 'X' STO
Y》

これは、1 行目で 1←X となり、2 行目で 1←X←Y になる。そして、3 行目で 2←X←Y になる。最後の行でに Y を評価しているが、2 がスタックに積まれることになる。最終行で起こっていることは、まず Y が指す X を評価され、その X は評価されて X が指す 2 が評価され、2 は評価されると自分自身をスタックに積むというというものである。

クオートされていないローカルな名前を入力すると、名前が指すオブジェクトの種類にかかわらず、それがスタックに積まれる。ここがグローバルな名前とローカルな名前の最も違うところである。

このことを明確にする例を見てみる。もし、P が 1 をさし、Q が 2 をさしているとき、スタックの状態が次のようだったとする。

3:     'P'
2:     'Q'
1:    《→ X Y 《X Y +》》

このプログラムを実行すると 'P+Q' という代数オブジェクトがスタックに積まれる。ここで、X,Y はローカルな名前だったので、《X Y +》中でクオートされていない X, Y は (グローバルな名前のときのように)EVAL されることなく、ただそれらが指すオブジェクトによって置き換えられてスタックに積まれたのである。

《1 'X' STO 
2 'Y' STO 
X Y +》

というプログラムでは、X,Y はグローバルな名前である。これを実行すると、3 がスタックに積まれる。プログラム中で作成した名前であっても、それが仮引数として作成されたのでなければ、それはグローバル名前である。だから、インタープリタが X や Y に出会うと「それが指すオブジェクトを評価したもの」をスタックに積む。

IF,THEN など

「構造」には、ローカルな名前を作り出す構造のほかにもう一種類あって、それは IF,THEN などの制御構造である。IF,THEN などはそれ自体はオブジェクトではなく structural words と呼ばれる。

TYPE コマンド

TYPE コマンドは、オブジェクトのタイプを教えてくれる。レファレンス・マニュアルの 3-262 によると、オブジェクトのタイプには、

0実数
1複素数
2文字列
3実数の配列
4複素数の配列
5リスト
6グローバルネーム
7ローカルネーム
8プログラム
9代数オブジェクト
10二進数
11グラフィック・オブジェクト
12タグつきオブジェクト
13 Unit オブジェクト14 XLIB 名
15 ディレクトリ・オブジェクト
16 ライブラリ
17 バックアップ・オブジェクト
18 整数
19シンボリック・ベクトル/行列

ここまでがユーザオブジェクトとなっている。
他に組込みコマンドやシステムオブジェクトがある。
'X'
《→ X 
《X TYPE
'X' TYPE》
》

結果は X TYPE が 6グローバルネーム、'X' TYPE が 7ローカルネームだった。

名前が指すオブジェクトの種類を調べるためには、VTYPE コマンドを用いる。たとえば、名前 X がプログラムを指しているとき、VTYPE 'X' によって、プログラムというタイプを知ることができる。もし、X TYPE と打つと、X が指し示すプログラムがただちに実行されてしまうし、(プログラムそのものを入力すると、プログラムそのものがスタックに積まれるが、プログラムを指しているグローバルな名前を入力すると、プログラムは実行される)、'X' TYPE とすると、名前 X のタイプ「グローバル・ネーム」が報告されるので、VTYPE コマンドは有用である。

オブジェクトが入力されたときのアクションまとめ

The Contents of a Program("reference manual" 1-1)によると

Object                    Action			
--------------------------------------------------------
Command                   Executed.			
Number			  Put on the stack.		       
Algebraic or `Algebraic`  Algebraic put on the stack.       
String			  Put on the stack.		       	 
List			  Put on the stack.		       
Program			  Put on the stack.		       
Global name (quoted)	  Put on the stack.		       
Global name (unquoted)    Program executed.		       
                	  Name evaluated.		       
                	  Directory becomes current.	       	 
			  Other object put on the stack.    
Local name (quoted)	  Put on the stack.		       	 
Local name (unquoted)     Contents put on the stack	       

いくらか実用的な例(スタック内容のリスト化)

次は、スタックの内容を 1 つのリストにまとめるためのプログラム。レベル 2,3,4,... の内容をリストにして、レベル 1 にある置いた名前をつける。

《→ X
《DEPTH →LIST
X STO
X LIST→ DROP》
》

DEPTH はスタックサイズを示す整数を積むコマンド。→LIST コマンドはこの整数を消費したあと、その整数が示すサイズだけスタックの内容を消費し、それをリスト化してスタックに積む。3 行目冒頭の X はクオートされていないローカルな名前なので、それが指すオブジェクト(つまりリストと関連づけたいグローバルな名前)に置き換わる。最終行では、LIST→ コマンドで、→LIST コマンドによって消費されて空になってしまったスタックを復元している。最後の DROP は、この復元時にリストサイズが報告されるから、それを切り落とすもの。

こうして作ったリストオブジェクトの名前をスタックのレベル 1 に置いて

《→ X《CLEAR X EVAL LIST→ DROP》》

のようなプログラムを実行すると、現在のスタック内容がリストに保存されていたものに置き換わる。LIST→コマンドは、リスト・オブジェクトの内容をスタックに展開する。その前で X を EVAL しているのは、X がローカル変数なので、たんに X と書いただけではリストについている名前そのものがスタックに積まれてしまうからである。

対話的入力を行うには

プログラム実行時にユーザ入力を受け取る最も簡単な方法は、

《"YOUR NAME?" PROMPT MSGBOX》

である。プロンプトが出たら、"" に囲まれた任意の文字列 "Kabipan Otoko" など打鍵して [ENTER]。そのあと、[↰][CONT] で、プロセスを再開。メッセージボックスにあなたの名前が出る。なお、電卓内に停止中のプロセスがあるときは、画面上部に HLT が表示される。停止中のプロセスをすべて殺すには KILL コマンドを用いる。。

しかこれではかなり面倒くさい。名前を入力したらすぐさまプロセスが再開してほしい。

《"YOUR NAME?" "" INPUT MSGBOX》

INPUT コマンドはユーザ入力を文字列として受け取るコマンド。

MSGBOX ならば、'X' がほしいときは 'X' と打てばいいし、整数がほしいときは 123 などと打てばよい。プロンプトが出た後に、スタックを使って計算して、その結果を入力にすることもできる。INPUT は何でもかんでも文字列として受け取るので、考えようによっては不便なところがある。

次は、INPUT を使って入力した文字列がキー入力されたかのように扱ってスタックに積むプログラム。

《"ENTER NAME" "" INPUT STR→》

INPUT された文字列が "1 2 +" なら、STR→ はこの文字列の内容がまるでキー入力であるかのように扱い、結局 3 がスタックに積まれる。

ディレクトリ

ユーザが作成したオブジェクトはディレクトリごとに管理されるので、ディレクトリを適宜切り替えて使う。SD カードにあるディレクトリは、カレントディレクトリにすることはできない。まあ、これが通り一辺のお話。

私はスタックに詩を書き込んでおいて読むのに使えないだろうかと考えた。電卓に詩が入っていたら素敵じゃないだろうか? ファイルビューアのアプリがいろいろと公開されているからそれを使えばいいのだけれども、そこまですることもない。

スタックのレベル 1 に文字列として詩のテキストを入れておけば、[TOOL]["VIEW"] で、ちゃんと単語の切れ目で改行して、小さな字でたくさんの行を表示してくれる。入りきらなければ、[▲][▼]でスクロールできる。

詩のディレクトリを作っておけば、こっそりそのディレクトリに行けばいいのだ。CRDIR はカレント・ディレクトリの下にディレクトリを作ってくれる。'POEM' CRDIR でいい。"POEM" CRDIR ではない。こうすると、ディレクトリ・オブジェクトができて、それに POEM という名前がつく。POEM TYPE とやってみると、6 になる。6 は Global name である。

ディレクトリ移動は、[↰][FILES] で ["CHDIR"] を選んでもいいが、もっと味なやり方をしてみたい。次のようなディレクトリ構成になっているとしよう。(ちなみに BYRON は詩人の名前だ)

HOME ┬ TEXT ─ POEM ─ BYRON
     └ CASDIT

TEXT ディレクトリか、BYRON ディレクトリにいるなら、たんに POEM と打ち込めば、POEM ディレクトリに移動できる。POEM はクオートなしのグローバルな名前だ。グローバルな名前は、それを定義したときにいたディレクトリ以下のディレクトリから見える。POEM は TEXT ディレクトリで定義されているから、TEXT ディレクトリ以下のディレクトリから見えるのだ。クオートなしのグローバルな名前を評価すると、名前の指す対象が評価される。POEM が指しているのは特定のディレクトリ・オブジェクトだ。ディレクトリ・オブジェクトを評価すると、カレント・ディレクトリがそのディレクトリに変わる。ということで、TEXT 以下のディレクトリでは、たんに POEM と打てば目的の POEM ディレクトリに移動できる。

しかし、CASDIR からは POEM と打っただけでは移動できない。CASDIR からは TEXT というグローバルな名前に何が割り当てられているかわからないからだ。こうした場合、{TEXT POEM} というリストを評価すればいい。リストは評価されると、各要素が順番に評価される。だからまず TEXT というクオートなしの名前が指しているものが探される。TEXT は HOME で定義した名前だからどのディレクトリからも見える。こうしてカレントディレクトリが TEXT に移動する。次に、グローバルかつクオートされていない名前である POEM が評価される。こうして、正しいディレクトリにたどりつく。

もっとも、ディレクトリを指す名前を上書きしていなければの話である。HOME ディレクトリ内では、直下のディレクトリ名は上書きできないから、《HOME TEXT POEM》 というプログラムを作っておけば、確実にディレクトリ移動ができる。HOME はコマンド扱いなので、リストの中に入れることができないのでプログラムにしたのである。

数式エディタ(EQW: Equation Writer)

hp 50g には、数式を編集するためのアプリケーションがはじめから入っている。広い視点から言うと、これは algebraic と呼ばれるオブジェクトを編集するためのものだ。[↱][EQW] で起動する。多少癖があるが、使用頻度が高いだろから、いささかしつこく観察してみた。

以下ボタン名を [ボタン名] と表記する。シフトキーを用いる場合は、ボタンの上方に白またはオレンジで刻印されていて、シフトキーにより選択される機能を表す文字のほうを [ ] に入れて記す。メニューを選択する場合や、ソフトキーから入力する場合は、["アイテム"] と記す。また、以下ボタンAを押したままの状態でボタンBを押すことを、同時に押すと呼び、これを [ボタンA]+[ボタンB] と表記する。これに対して[ボタンA][ボタンB] は 2 つのキーの独立した連続的な操作を表す。

[↱]+[i] で、実数モードと複素数モードの切り替え。以下実数モードを前提。

[↱]+[ENTER] で、概数モードと厳格モードを切り替え。以下厳格モードを前提。

数式の打ち込み

数式エディタは立ち上げたときは文字を挿入できるモードになっている。RPN 方式ではなく、中置記法で書く。

数式エディタで演算子を打ち込むと、後から打った演算子が優先される。あるいは、カーソルの直前にある数をオペランドとして演算子が入力されると言ってもよい。

この仕様は右結合の演算子の場合ごく自然に思える。たとえば をわれわれは 2^(1^3) と解釈するが、hp 50g の数式エディタにおいても [2][x^y][1][x^y][3] の順でキーを押せばこれが入力できる。これは [EVAL] すると、2 になる。

[÷] は一般的に左結合で、われわれは 1÷2÷3 を (1÷2)÷3 と解釈する。しかし、hp 50g の数式エディタで [1][÷][2][÷][3] の順で打ち込むと、後から打ち込んだ 2 つ目の ÷ のほうが優先され 1÷(2÷3) と解釈する。したがって、[EVAL] すると 3/2 となる。

もっとも、この 1÷(2÷3) は実際の液晶画面では次のようになるので、そう違和感はない。(これは、私の持っている他の数式通り関数電卓も同様だ。)

なお、数式エディタを立ち上げずにスタックに入力する場合 ['][1][÷][2][÷][3] と打鍵すると '1/2/3' と入力され、これは (1/2)/3 の意味に解される。

[+] はふつう左結合なので、われわれは 1+2+3 という式を見ると (1+2)+3 と解釈する。しかし、hp 50g の数式エディタは後から打鍵した [+] が優先される。したがって、[1]+[2]+[3] は、画面上には 1+2+3 と表示されるものの、1+(2+3) と解釈される。もっとも、+は結合法則が成り立つので問題がない。[×] についても同じである。

一般に+と×では、×のほうが優先されるが、hp 50g の数式エディタは後から打った演算子を優先する。したがって、[1][×][2][+][3] は、1×2+3 ではなく 1×(2+3) と解釈され、[EVAL] すると 1/5 となる。ただし、液晶画面の表示は自動的に( )が挿入されて 1・(2+3) となってるから、勘違いすることはない。

1 項演算子を打つと、挿入カーソル直前に演算子が入力され、カーソルはオペランド入力待ちになる。したがって、sin(1) と打ちたちときは、[SIN][1] の順で打てばよい。

2-1 などというときの - や、負の数をあらわす - については、多少複雑な事情があるので後述。

範囲の選択

打ち込んだあと [◀][▲][▶] で、式の一部分を選択状態にすることができる。すでにいずれかの部分が選択状態にあるとき、[▲]キーは選択範囲を広げ、[▼]は選択範囲を狭める。また、[◀][▶] で選択される範囲を左右に変えることができる。とはいっても、これらによってテキストエディタでのように、表示された式の任意の部分を選択きるというわけではない。たとえば、1*2+3 と打ち込んだときは、(((1)*(2))+(3)) のうちの ( ) で囲まれた部分のいずれか一つを選択範囲にすることができるだけである。以下、図では ( ) を使うと見づらいので、代わりに木で示す。木には左右がある。(このページの図はあくまでも「そう考えてもいいじゃん?」という私の憶測。)

項の和からなる式において、結合法則によって括弧でくくれる部分は範囲として選択できる。選択範囲は [↱][▶] で、右方向に伸張され、[↱][◀] で左方向に伸張する。なお、このようなやり方で選択範囲を短かくすることはできない。

選択範囲が最も狭まっているときに[▼] を押すと、カーソルが黒(文字白抜き)から、枠だけのものに変わる。このとき、[◀][▶] によって、階層を無視してツリー構造の末節を移動することができる。

ソフトキーの ["CURS"] を押すと、[◀][▶][▲][▼]によって画面上を自由に動かせるポインタが出てきて、これを使って選択部分を選ぶことができるようになる。しかしこれによって、選ぶことができる部分が増えるわけではない。

どのようにしても + だけや * だけを選択する方法はない。 あるいはこの例では 2+3 を選択範囲にすることはできない。

範囲選択状態での入力

(1) 式の部分が選択されている状態で、数や変数といったオペランドをとらないものを打ち込むと、選択された部分が、打ち込んだものによって置き換わる。

(2) 式の部分が選択されている状態で、1 つのオペランドをとる演算子を入力すると、選択部分が演算子に置き換わり、以前選択されていた部分がその演算子のオペランドになる。

(3) 式の部分が選択されている状態で、2 つのオペランドをとる演算子を入力すると、選択部分が演算子に置き換わり、以前選択されていた部分がその演算子の一つ目のオペランドになり、二つ目のオペランドの入力をうながされる。

[↱][CLEAR]

[↱][CLEAR] は、選択範囲となった部分木全体を削除したうえで、削除された場所への入力を待つ挿入カーソルを出してくる。選択範囲は、いつでもこのように [↱][CLEAR] することができる。

[↰][DEL]

[↰][DEL] は、選択範囲となった部分木の最上部にある節点を削除する。挿入待ちのカーソルは出してこない。

(1) 二項演算子のオペランドのうちの 1 つが [↰][DEL] されると、残ったもう片方のオペランドが二項演算子の場所を奪う。

次の例では、最上部節点は 1 そのものであるので、その相方のオペランドである 3 が二項演算子^の位置を奪っている。

次の例では、最上部節点が^であり、やはり同じ規則で説明できる。

(2) 一項演算子を [↰][DEL] すると、その演算子はオペランドによって置き換えられる。

(2) は (1) より優先される。したがって、

(3) 選択中された部分木の上位にある節点がオペランド不足になるであろう場合は、 [↰][DEL] の実行が認められない(ビープ音がする)。

[←]

範囲選択がなされているときに [←] キーを押すと、選択中の部分木の中で、右下端の節点をあらわす文字または文字列のすぐ右に挿入カーソルが現れる。これはたいがいの場合、画面上における選択範囲のすぐ右側であるが、そうとはならない場合もある。

挿入カーソルが現れている状態で [←] キーを 1 回押すたびに、直前の数や演算子が消去される。このとき数は下から 1 ケタずつ消すことができる。

[−](マイナス)

減法を表す 2 項演算子としての -(マイナス)は存在しない。- は 1 項演算子であり、オペランドの符号を反転させる。したがって、2-1 は 2+(-1) と表現される。ただし、画面にはこれが 2-1 と表示される。

このことは、1+2 と 1-2 で、2 が選択された状態から [▲] を押したときに起こることの違いにあらわれている。1+2 では、1+2 全体に選択範囲が広がるが、1-2 では -2 が選択範囲になる。

− 演算子の親が + 演算子になっている場合、− 演算子を頂点とする部分木を選択範囲として [↰][DEL] すると、一般の [↰][DEL] とは異なる例外的なことが起こる。原則通りなら -1+2 の -1 に対して [↰][DEL] を実行すると − だけが削除されて 1+2 になるはずだが、実際は 2 になる。

- 演算子の親が + 演算子以外の場合は原則通り。たとえば、-1・2 と表示されているとき(- 演算子のほうが・演算子より優先度が高いので、これは (-1)・2 の意味)に、 -1 を選択して [↰][DEL] すると、1・2 になる。

——目次——
HOME雑文写真壁紙馬鹿読書語学
│├英語
│└日本語電算地理
│└白地図ブログ