読者です 読者をやめる 読者になる 読者になる

電卓考(draft)

世界で最もポピュラーなディジタルガジェットと思われる電卓であるが、いろいろと考えてみるに、歴史的な理由による制限や互換性を保つために不自然な設計になっている部分があるように思う。特にコンピュータ上のGUIアプリでは、たとえばコストを気にせず表示を複数にできる(スマフォアプリでは大きさの問題があるが)ことなどから改善の余地があるのではないか、という話。

そもそも電卓とは

普通の電卓は算術における式と基本的に同じ順番で入力すれば使えるため「式を計算してくれるもの」と誤解されやすいが(また、プログラミングの題材で「電卓」と言った場合、たいていは算術式をパースするものを実装するが)、近年の関数電卓にはそういったものもあるがともかく、実際には機械式計算機と同じように「機械を操作して計算させるもの」であると考えるべきであろう。

特に 1 + 2 * 3 = のように操作して 9 になるという点など、たとえば教育目的などの場合に、教育用などとして関数電卓のように乗算を先にする電卓を作ったりするのは良くないと考える。機械の仕組み全てを考えるのは無理があるとしても、簡単化したモデルを把握することが重要である。

電卓のモデル化

普通の電卓のモデルを以下に述べる。置数レジスタとテンポラリレジスタの2つのレジスタがある。数字ボタンで数を入力する対象となるのが置数レジスタで、演算のために必要なもう片方の値を記憶しているのがテンポラリレジスタである(コンピュータの命令系でいう、いわゆる2アドレス型の演算しかできない、と考える)。

表示は、置数の入力中は置数レジスタの内容が、= ボタンや演算子ボタンを押した直後は演算結果が表示される。演算子ボタンを押した場合についても演算結果が表示される、ということについては、1 + 1 + と操作して、2 度目の + の直後は 2 と表示されることで確認できるだろう。実機としては表示させるためにレジスタが必要だが、そういったことは後述する。

以上の演算対象の数を記憶するレジスタの他に、入力されている演算の種類を記憶するレジスタも必要である。1 + 2 = と操作した場合の 2 の入力中に、次にすべき演算が加算であることが記憶されていなければならない。高級機では実際に演算子を示す表示があるものもある。

このように電卓をモデル化することで、たとえば 1 + 2 * 3 = 7 といったような計算をするためには、「 "1" を記憶するレジスタ」「 "+" を記憶するレジスタ」「 "2" を記憶するレジスタ」「 "*" を記憶するレジスタ」が必要で、普通の電卓のしくみはそうなっていないから、そのように計算するのは不可能であること、そういった計算ができる関数電卓はつくりが違うこと、といったことが了解できる。関数電卓や加算機方式についてはまた別に(気が向いたら)書く。

実機の実装

近年の電卓は、ほぼ全てがカスタム超省電力ワンチップマイコンを使いソフトウェアで実装されているはずだが、ここではマイコン以前の実装法を考える。ソフトウェアによる実装でも、操作を変えないために以前の方法をシミュレートするようにして作られていると言ってよいはずである。

まず、レジスタとしてXレジスタと呼ばれているレジスタがある。Xレジスタは表示器に直結している。もうひとつのレジスタがYレジスタである。ハードウェアを単純化するためにはこのような構成になるわけで、昔の電卓では演算中、特に除算やルートの計算など時間がかかる処理中は表示器がチラチラするのが実際に目に見えていた。

表示器に直結している関係上、数値の入力中はXレジスタは前述の置数レジスタとして働く。表示器が1個というコスト上の絶対的な都合から演算結果もXレジスタに置かざるをえず、「演算結果表示状態」から数値ボタンが何か押された時点で(必要なら結果をYレジスタにコピーしてから)Xレジスタをクリアし、Xレジスタが置数レジスタとして働く状態に遷移する。

「必要なら結果をYレジスタにコピーしてから」というただし書きについて説明する。1 + 2 + 3 + ... といったように、演算子ボタンで演算を続けている間は、直前の演算結果が、直後の演算の対象となるので、表示のためにXレジスタに入っている演算結果をYレジスタにコピーしないといけない。一方 = ボタンで演算をした場合は、いわゆる定数計算モードとして、たとえば 2 + 3 = と操作した後は 5 = と入力すれば 5 + 3 を、といったように X + N を計算するようになるので、演算結果は保存せず定数 N に相当する値が Y レジスタに残るようにしなければいけない(定数モードはカシオ機は動作が異なる)。

詳細は、そこそこエミュレータ的になるようにシミュレータを実装してみたので( http://metanest.jp/u9kjmxinstub7/dentaku.html 、URLは暫定)本気で興味がある方はソースを見るとかしてみてほしい。実機(シャープ EL-306 )の調査を元に基本的には同様に動作するよう構成したが、明確に違う動作としては、1 + = のように、演算子ボタンの直後に = ボタンを押した場合の動作は違うものになっている(実機では 3 ÷ = のようにすると 0.333... のように除算の場合は 1 がオペランドになったり、不思議な動作をする)。

Yレジスタが実際に見えることで、電卓に対する理解が深まるのではないか、と期待して作ってみたものだが、小数点ボタンや、ちゃんとした電卓らしい十進演算などは未実装である。

実機のUIを越えて

表示器をたくさん付ければ、電卓はもっと違ったものになる、という提案は他の人によるものも既に多くあるはずであるが、ここでは旧来の電卓について深く考えることで何かわかることはないか、というアプローチをとってみた。先行文献としては、祝一平氏が「皿までど~ぞ」だったか「人類タコ科図鑑」だったかで、たくさん表示器の付いた電卓を提案しているのを見た記憶がある。

少し前に話題になった「iPhoneの電卓だと「2500÷50=1」になる!? 衝撃の結果」( http://nlab.itmedia.co.jp/nl/articles/1401/22/news120.html )という話についても、直接の原因は実機の電卓のように = を押した直後に表示が一旦消えてまた点くという現象が無いせいであるが、Yレジスタが表示されていても回避される問題だと言える。

実際にYレジスタを見えるようにしてみると、なんだかんだで表示器が1個ということに縛られてレジスタをとっかえひっかえする感じになっている部分が見えると思う。まだ頭の中で考えている状態だが、表示器を増やすことで従来の加算機方式をベースとした「よりわかりやすい加算機方式」ができるかもしれないし、あるいはスタックの中身が見えれば RPN 方式が最強ではないか、という気もする(それが言いたかっただけでは? というツッコミは却下)。