2023年9月18日月曜日

HP-15Cで余りを求めるプログラムを作る

 本ブログにたまーに登場する、ヒューレット・パッカードのプログラム電卓、HP-15Cの記事です。写真がそのHP-15Cです。(この電卓についてウダウダと書いた説明はこちら。)


先日、秋分の日について調べていて、西暦年を4で割った余りと、秋分の日が9月の何日か、ということに関連性があるっていうことをWikipediaで見つけたんです。


西暦年を4で割った余りが秋分の日と関連性があることは分かったけど、余りの計算ってHPの電卓で出来なかったかな?と思って調べてみたけど、この電卓には商と剰余演算は実装されていません。商は、割り算の答えの整数部ということになるので、小数点以下を切り捨てるためのINT関数を使って計算することはできます。例えば5を3で割った商は、

5[ENTER] 

3[÷]

[g][INT]

で計算できます。一手間増えますが、比較的楽に計算できますね。そもそも小数点以下を無視すれば良いので、改めてINT関数を適用することもないかもしれません。しかし、これに比べると、余りは電卓ではそんなに単純には計算できません。

割る数、割られる数、商、余りは以下の関係になりますよね。

割られる数 = 割る数 × 商 + 余り

余り = 割られる数  割る数 × 商

商が割り算の整数部であることを加味すると、

余り = 割られる数  割る数 × (割られる数 ÷ 割る数)の整数部

ということになります。例えば、上記の例と同様に5を3で割った場合の余りを、HP-15Cで手計算で求めるのであれば、

5[ENTER]

3[ENTER]

5[ENTER]

3[÷]

[g][INT]

[×]

[]  

となると思います。

何でこんな変な入力方法になるのか、ということについては、以前こちらに少し書いたスタックの説明がヒントになるかも知れません。スタックの動作に関する理解が必要と思います。なお、もう少し効率の良い計算の仕方があるかもしれませんが、この場はこれで行きます。

ここで面倒なのは、数式の中、に割る数、割られる数ともそれぞれ2回ずつ出てくることです。手計算だったら上記の入力手順で良いと思いますが、プログラムで計算させるということになると、割る数、割られる数とも入力は1回で済ませたいわけでして、割る数、割られる数ともメモリーに入れて、メモリーとメモリーの計算をさせる、というのが素直な解決方法だろうと思います。

つまり、

割られる数をメモリー0に入れる

割る数をメモリー1に入れる

メモリー0をメモリー1で割って、その整数部を求める・・・(1)

割る数と(1)をかける             ・・・(2)

割られる数から(2)を引く

とゆう手順になると思います。割られる数を入力して[ENTER]、割る数を入力してプログラムスタート、という前提で、プログラムにしたものが以下です。


001 - 42,21,14         プログラムをDキーにラベル付け

002 - 44 1 Xレジスタ(割る数)をメモリー1へ格納

003 - 33 スタックを一段下げる(最初に入力した数値がXレジスタへ)

004 - 44 0 Xレジスタ(今度は割られる数)をメモリー0へ格納

005 - 45 0 Xレジスタに割られる数を転送

006 - 45 1 Xレジスタにメモリー1(割る数)を転送

007 - 10 YレジスタをXレジスタで割る(結果はXレジスタ)

008 - 43 44 Xレジスタの小数点以下を切り捨て

009 - 45 1 Xレジスタにメモリー1(割る数)を転送

010 - 20 YレジスタとXレジスタをかけ算(結果はXレジスタ)

011 - 30 YレジスタからXレジスタを引き算

012 - 43 32 リターン

割られる数[ENTER]、割る数[f]Dで動きます。



起動時点でXレジスタに入っているのは、最後に入力した割る数なので、これをまずメモリー1へ転送します(行番号2)。次に最初に入力した割られる数をXレジスタに入れるためにスタックを1段下げ(行番号3)、Xレジスタをメモリー0に転送します(行番号4)


次に改めてメモリー0の割られる数をXレジスタに転送します。これによってスタックが1段上がり、XレジスタとYレジスタに割られる数が入っている状態となります(行番号5)。今度はメモリー1の割る数をXレジスタに転送します。これによってスタックが1段上がり、ZレジスタとYレジスタに割られる数、Xレジスタに割る数が入っている状態となります(行番号6)


割り算を実行します。Yレジスタの内容をXレジスタの内容で割り、結果がXレジスタに入り、スタックが1段下がってZレジスタの内容がYレジスタに転送されます。つまりYレジスタには割られる数が入っています(行番号7)


INT関数で小数点以下を切り捨て、結果がXレジスタに入ります。スタックに変化はありません(行番号8)


Xレジスタにメモリー1(割る数)を転送します。スタックが1段上がるので、行番号8の結果はYレジスタに、Yレジスタにあった割られる数はZレジスタに転送されます。(行番号9)


かけ算を実行します。XレジスタとYレジスタの内容をかけ算して、結果がXレジスタに入ります。割る数と商のかけ算をしたことになります。Yレジスタには、Zレジスタに入っていた、割られる数が入ります(行番号10)


引き算を実行します。YレジスタからXレジスタを引いて、結果がXレジスタに入ります。割られる数から、割る数と商を掛けたものを引いたことになります(行番号11)。つまり余りですね。


今回、意地になってプログラムを書きましたが、余りの計算って、実はあんまり使わないですよね。


学生時代に使っていた8ビットパソコンのFM-77で走るF-BASICには剰余演算子があって、これで余りの計算が出来ていましたが、シャープのポケコンのBASICには実装されていなかったりするので、あんまり用途のない機能なのかもしれません。


それではまた。


0 件のコメント:

コメントを投稿

何か一言頂ければ・・・