先日,MODを計算する機会があった. MODとは合同算術,すなわちModular Arithmeticの略で,剰余を持つ除法のこと. この場合,余り計算を指す. 例えば5mod2は,5/2の結果が商2余1であるので答えは1. この y mod x なる計算を行う必要があった. yの値が16807と大きな数であったのでHP15Cで計算できると便利だと思ったが,この計算機にはmodキーが無い. そこで,modをプログラムすることとした. y mod x の計算方法は次の通りである.
$$ y\ mod\ x = y - x\times \lfloor \frac{y}{x} \rfloor$$
- まずy/xを計算する. これをaとする. ここでaは実数である.
- aの小数点以下を切り捨てる. ここでaは整数となる.
- a*xを計算し,yからa*xを減ずる. これをrとする.
- rが y mod x の解となる.
レジスタを用いたMOD計算
さて,この計算をプログラムするにあたり,まず思いついた方法はレジスタを2つ用いるやりかたであった. 以下に 7 mod 2 での15Cのスタック遷移とプログラム例を載せる.
( x y z t) [キー] 説明
( 2 7 0 0) [P/R, LBL A] ラベルAとしてプログラム開始.
( 2 7 0 0) [CLEAR REG] 全レジスタクリア.
( 2 7 0 0) [STO 1] スタック先頭をレジスタ1にコピー.
( 7 2 0 0) [X≷Y] スタックXとYの内容を交換.
( 7 2 0 0) [STO 2] スタック先頭をレジスタ2にコピー.
( 2 7 0 0) [X≷Y] スタックXとYの内容を交換.
(3.5 0 0 0) [DIV] 除算÷
( 3 0 0 0) [INT] 整数へ変換.
( 2 3 0 0) [RCL 1] レジスタ1の内容をスタック先頭へ復帰.
( 6 0 0 0) [MUL] 乗算×
( -6 0 0 0) [CHS] 符号を変える.
( 7 -6 0 0) [RCL 2] レジスタ2の内容をスタック先頭へ復帰.
( 1 0 0 0) [ADD] 加算+
( 1 0 0 0) [CLEAR REG] 全レジスタクリア.
( 1 0 0 0) [RTN] リターン.
( 1 0 0 0) [P/R] プログラム終了.
プログラムを試す.
映像30秒~のように上手く計算出来た.( 2 7 0 0) [P/R, LBL A] ラベルAとしてプログラム開始.
( 2 7 0 0) [CLEAR REG] 全レジスタクリア.
( 2 7 0 0) [STO 1] スタック先頭をレジスタ1にコピー.
( 7 2 0 0) [X≷Y] スタックXとYの内容を交換.
( 7 2 0 0) [STO 2] スタック先頭をレジスタ2にコピー.
( 2 7 0 0) [X≷Y] スタックXとYの内容を交換.
(3.5 0 0 0) [DIV] 除算÷
( 3 0 0 0) [INT] 整数へ変換.
( 2 3 0 0) [RCL 1] レジスタ1の内容をスタック先頭へ復帰.
( 6 0 0 0) [MUL] 乗算×
( -6 0 0 0) [CHS] 符号を変える.
( 7 -6 0 0) [RCL 2] レジスタ2の内容をスタック先頭へ復帰.
( 1 0 0 0) [ADD] 加算+
( 1 0 0 0) [CLEAR REG] 全レジスタクリア.
( 1 0 0 0) [RTN] リターン.
( 1 0 0 0) [P/R] プログラム終了.
スタックのみを用いたMOD計算
しかし,上手く行くと欲が出る. 15Cのスタックは4つ有るので,レジスタを用いずにスタックだけで計算出来る筈だからだ. スタック内を少しこね回すだけで,レジスタを使うことなく余り計算を行えるようになる. 以下にそのスタック遷移とプログラム例を載せる.
( x y z t) [キー] 説明
( 2 7 0 0) [P/R, LBL A] ラベルAとしてプログラム開始.
( 2 2 7 0) [ENTER] 入力終わり(スタック先頭をコピー).
( 2 7 0 2) [R↓] スタック全体を下へ移動.
( 7 2 0 2) [X≷Y] スタックXとYの内容を交換.
( 2 7 2 0) [R↑] スタック全体を上へ移動.
( 7 2 2 0) [X≷Y] スタックXとYの内容を交換.
( 7 7 2 2) [ENTER] 入力終わり.
( 2 7 7 2) [R↑] スタック全体を上へ移動.
(3.5 7 2 2) [DIV] 除算÷
( 3 7 2 2) [INT] 整数へ変換.
( 2 3 7 2) [R↑] スタック全体を上へ移動.
( 6 7 2 2) [MUL] 乗算×
( -6 7 2 2) [CHS] 符号を変える.
( 1 2 2 2) [ADD] 加算+
( 1 2 2 2) [RTN] リターン.
( 1 2 2 2) [P/R] プログラム終了.
このプログラムを試すと,
計算終了後(32秒あたり),Xスタックに解である余り1が,また34秒~に見えるように他3つのスタックY,Z,T全てに y mod x 中の値xが代入された状態となる. このプログラムならレジスタを他の用途で使っていても気楽に計算出来る. 上手くプログラムすればもう少し手数を減らせるのだろうか. まぁ上手く動いているから気にしない.( 2 7 0 0) [P/R, LBL A] ラベルAとしてプログラム開始.
( 2 2 7 0) [ENTER] 入力終わり(スタック先頭をコピー).
( 2 7 0 2) [R↓] スタック全体を下へ移動.
( 7 2 0 2) [X≷Y] スタックXとYの内容を交換.
( 2 7 2 0) [R↑] スタック全体を上へ移動.
( 7 2 2 0) [X≷Y] スタックXとYの内容を交換.
( 7 7 2 2) [ENTER] 入力終わり.
( 2 7 7 2) [R↑] スタック全体を上へ移動.
(3.5 7 2 2) [DIV] 除算÷
( 3 7 2 2) [INT] 整数へ変換.
( 2 3 7 2) [R↑] スタック全体を上へ移動.
( 6 7 2 2) [MUL] 乗算×
( -6 7 2 2) [CHS] 符号を変える.
( 1 2 2 2) [ADD] 加算+
( 1 2 2 2) [RTN] リターン.
( 1 2 2 2) [P/R] プログラム終了.
439582129191023036
https://www.storange.jp/2013/07/mod.html
https://www.storange.jp/2013/07/mod.html
MOD計算
2013-07-30T21:17:00+09:00
https://www.storange.jp/2013/07/mod.html
Hideyuki Tabata
Hideyuki Tabata
200
200
72
72