Casio Basic入門32
Casio Basic入門
誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
最終: 2015/01/25
最終: 2015/01/25
4. CasioBasicを使ってみる(続き)
前回: Casio Basic入門31 (Chapter 5)を見る
お詫び
※ 本Chapter 6 は、Chapter 3 の続編で、Chapter 3 で作ったプログラムを高速化するのが 本Chapter 6 の目的です。なお、Chapter 3 自由自在に入力する の Caso Basic入門17 と Casio Basic入門18 を修正・追記しています。 特に Casio Basic入門18 は誤記や説明不足が多くあり、多くの部分を修正・追記しています。申し訳ありません。必要に応じて、もう一度ご覧ください。
Chapter 6
◆ Chapter 6 の目標: プログラムを速くする
入力ボックスの改良と拡張
はじめに
Chapter 3 - 自由自在に入力する - で作った入力ボックス サブルーチン INPI Ver 1.0 は、0以上の正の整数の入力のみに対応しています。これを正負小数入力に対応するために、必要な処理を追加して拡張したものを作って、使っていましたが、入力応答がとても遅くて、入力時にストレスを感じているので、公開には至っていません。個人的に我慢して使っていると言う状況でした。
最初から、高速応答するように作っていれば良かったのですが、私自身も Casio Basic を手探りで調べながら、分かったことを公開しているので、拡張してみてから応答が非常に遅くて実用に耐えられないので、これをなんとか改善したいと思っていました。
そこで、遅いプログラムの高速化の具体例として、入力ボックスを高速応答させるための改良方法を紹介します。そして今回作る拡張版入力ボックスを活用して頂きたいと思い、プログラムライブラリ にも収録しました。
但し、Chapter 3 はそのまま残します。私の失敗を公開することで、これをお読みの方が同じ失敗に陥らなければ幸いです。
実際に行ったこと
さて、最終的に正負小数に対応した入力ボックス IN を高速化して、ストレスの無い入力ができるようになりました。さらに高速化したことで、機能拡張もてきました。この時の考え方や手法を、今回 Chapter 6 で紹介します。
実際に私が手元で行った改良と機能拡張の流れと、作った機能拡張版 (INPとIN) は以下の通り;
入力ボックス | 機 能 |
INPI | 0との正の整数の入力に対応 |
INP | 0 と正の整数と正の小数の入力に対応 |
IN | 0 と正負整数と正負小数の入力に対応 |
1) INPI Ver 1.0 を拡張し、0と正の小数に対応した INP Ver 1.0 および 正負小数に対応した IN Ver 1.0 を作成
2) INPI を高速化して Ver 1.2 とした
※ INPI Ver 1.2 をプログラムライブラリで公開。応答速度は許容範囲と判断したものの、まだ物足りない。
3) 同じ手法を INP と IN に適用して、Ver 1.2 とした。
※ INP Ver 1.2 と IN Ver 1.2 はまだ遅いので、非公開のまま。
4) INPI Ver 1.2 をさらに見直して Ver 2.0 とした
※ 入力応答を速くするために、ロジックを変更。
※ INPI Ver 2.0 は十分に満足できる応答速度になった。
5) 同じ手法を INP と IN に適用して、Ver 2.0 とした
※ INP Ver 2.0 と IN Ver 2.0 共に実用上許容範囲の応答性になった。
6) IN, INP, INPI Ver 2.0 のキーリピート抑制バージョンとして Ver 2.1 を作成
※ 以上は fx-5800P 専用入力ボックス
7) Ver 2.1 をグラフ関数電卓 (fx-9860GII、fx-CG20、CG50)に対応にした Ver 2.1G を作成
[2015/01/09 追記]
INPI Ver 2.0 は最初のバージョン 1.0 の2倍の入力応答速度が得られ、十分満足できるレベルになっています。INP Ver 2.0 や IN Ver 2.0 についても、下表のように実用上ストレスを感じない応答性が得られています。
改善した入力ボックス 2.0 の応答性能まとめ
バージョン | 10桁入力の所要時間 | 1秒間のキー入力回数 |
INPI Ver 1.0 | 2.8秒 | 3.5回 |
INPI Ver 1.2 | 2.2秒 | 4.5回 |
INPI Ver 2.0 | 1.4秒 | 7.1回 |
INP Ver 2.0 | 1.8秒 / 1.6秒※1) | 5.5回 / 6.2回※1) |
IN Ver 2.0 | 1.8秒 / 1.6秒※2) | 5.5回 / 6.2回※2) |
※1) [小数入力時] / [整数入力時] 、1.8秒 および 5.5回は、小数入力時のデータ 。
※2) [負の小数入力時] / [整数入力時] 、1.8秒および 5.5回は、負の小数入力時のデータ。
INPI のロジック見直し(Ver 2,0) の効果が顕著に表れていることが分かります。
INP Ver 2.0 と IN Ver 2.0 は結果的に応答性に大きな差がありません。
ようやく実用的な入力ボックスができたと思います。
Chapter 6 の内容
実際の検討内容通りに紹介すると、私の試行錯誤にお付き合い頂くだけで無駄が多過ぎるので、Chapter 6 では、以下の流れで進めることにします。Chapter 6 では実際に行ったプログラム高速化の手法を紹介します。
1) INPI Ver 1.0 から Ver 1.2 への変更
※ 遅い処理を可能な限り排除する。
2) INPI Ver 1.2 から Ver 2.0 への変更
※ プログラムの内部仕様(ロジック)変更を行い、その高速化を実感してもらう。
3) INPI Ver 2.0 を拡張してINP Ver 2.0 を作る
※ 小数入力への対応方法を紹介する。
4) INP Ver 2.0 を拡張してIN Ver 2.0 を作る
※ 負の数入力への対応方法を紹介する。
Chapter6-0
コマンドや命令の処理速度を比較する
fx-5800P は、通常使用なら単4電池で1年程度動作するとカシオのホームページに書かれています。この省電力化は、CPU の動作クロックを遅くすることに繋がり、上位機種 (fx-9860GII、fx-CG20 や fx-FD10 Pro など) よりも Casio Basic の動作速度がかなり遅く抑えられています。
そこで、INPI Ver 1.0 を Ver 1.2 に変更するにあたり、プログラム動作を遅くする Casio Basic のコマンドや命令を探し出し、それを極量使わないようにプログラムを変更します。
ちなみに、Casio Basic は、メモリに保存されているプログラムがリアルタイムで読み取られ、CPUを動作させる命令に翻訳されながら動作します。翻訳して動作するので、Casio Basic はインタープリター(通訳という意味)型の言語に分類されます。つまり、遅いコマンドや命令を排除することで、プログラム全体の顕著な高速化が期待できます。言い換えれば、最初から高速動作を念頭に入れてプログラムを書くべきとも言えます。Chapter 3 の入力ボックスでは、それがうまく出来ていなかったことになります。
パソコンで使うプログラムの多く、そしてカシオの上位機種 fx-9860GII などでSDKを使って作れる C 言語などのプログラムは、プログラミング言語で作ったファイルを一旦変換して実行ファイルや中間ファイルと呼ばれるものを作り、それが実行されます。実行ファイルや中間ファイルを作る時には、無駄なく高速に動作するように最適化処理が行われるので、遅いコマンドや命令単位を排除しても、Casio Basic のような顕著な高速化が期待できません。前向きに考えれば、工夫次第で顕著な高速化が可能なのが fx-5800P Casio Basic の面白いところです。
さて、プログラムを構成する主な要素には、以下のようなものがあります。
・ループ処理
・条件分岐処理
・論理演算や比較演算
・算術演算
・変数アクセス(変数の値の読み出しと書き込み)
これらの中から、特に処理速度の遅いものを探し出すために、主要なコマンドや命令の速度比較を行います。
ループ処理や条件分岐処理については、単純な制御構造について以前調べて以下にまとめているので、ご覧ください。
⇒ fx-5800P コマンドの処理速度
※ 制御構造とは、プログラムを構成する命令やコマンドを実行する順序のことです。プログラムは通常上から下へ実行され、If 文や⇒命令、Dsz/Isz命令 による条件分岐、Goto/Lbl などの無条件分岐や Do/While/For 文などのループ処理、そして Prog コマンド によるサブルーチン呼び出しがある時だけ、この原則を破ってすぐ下の処理ではなくて、別のところへジャンプします。分岐やループの処理の無いプログラムは最も単純な制御構造を持っています。分岐やループ、サブルーチン呼び出しが多くなるほど制御構造が複雑になります。
ループ処理については、Casio Basic では以下の4種類があります。
・Lbl / Goto ループ
・Do ループ
・While ループ
・For ループ
以前単純な制御構造で調べた結果は、これらのどれも大きな差はなく、上記のループの種類を変えても、速度向上には殆ど寄与しない結果が得られています。但し、複雑な制御構造を持つプログラムでは未確認です。
プログラムが長く複雑になって結果的に制御構造が複雑になるとLbl / GOTO ループは速度が極端に低下することが経験的に分かっていますので、今回はこれについても調べる予定です。
一方、条件分岐については、以下の3つ;
・条件ジャンプ命令 ⇒
・If 文
・Dsz/Isz命令
調べた結果は、以下のようになります。ここにも工夫の余地があります。
変数が0 (偽) か、そうでない (真) かによる条件分岐
If [変数] よりは、[変数]⇒ の方が2倍程度速い。
[式] が真か偽かによる条件分岐
If [式] よりは、[式]⇒ の方が、1.5 倍程度速い。
複数条件による分岐
[式/変数]⇒ を2つ以上記述するよりも、If [式/変数] Then~Else~IfEnd の方が速い。
Isz / Dsz
A+1→A よりも Isz A の方が2倍程度速い。
次に、変数アクセス、比較・論理演算、条件分岐の処理速度比較を、以下で行いました。
⇒ 変数アクセス、比較・論理演算、条件分岐の速度比較
その結果は、
制御変数 (インデックス) を使った配列へのアクセス(読み出しと書き込み処理)
これらには、配列変数、行列、リストが使える。
これらの読み出しや書き出しは非常に遅いが、使う場合はこれらの中で相対的に速いのが「配列変数」。そこで配列には「配列変数」を使うべき。但し、そもそも配列変数へのアクセスは遅いので、読み出しや書き込みの回数を極力少なくするべき。
比較演算や論理演算
これらは、算術演算(+、-、×、÷)よりも遙かに遅い。さらに変数同士の比較演算や論理演算処理の方が、変数と数値(即値)との処理よりも少し速い。従って、即値(数値)はできるだけ使わず、さらに比較演算や論理演算を使う回数を減らすべき。
条件分岐
条件判定に使う比較演算や論理演算が、条件分岐処理の殆どの時間を占める。さらに条件判定には、変数同士を用いる方が、変数と即値(数値)を用いるよりも少し速い。
この結果を一覧にしたのが以下の表です。
表 fx-5800P Casio Basic 処理時間の比較
処理内容 | 処理時間※ (ミリ秒) |
A⇒ | 4.1 |
通常変数アクセス | 5.4 |
If A | 6.2 |
If A Else | 7.2 |
比較演算(変数) | 9.7 |
A≠B⇒ | 10.0 |
論理演算 | 10.0 |
比較演算(数値) | 11.5 |
If A≠B (変数) | 12.0 |
if A≠0 (数値) | 13.7 |
テキスト表示 (Locate) | 20.4 |
配列変数書き込み | 22.0 |
配列変数読み出し | 22.7 |
リスト読み出し | 25.1 |
リスト書き込み | 25.3 |
行列読み出し | 26.9 |
行列書き込み | 28.4 |
同様の方法で、掛け算 (乗算)、割り算 (除算)、累乗、整数部を取り出す関数 Int( ) の処理時間を調べて見ると以下のようになり、上記の調査結果と比べると、これらの演算は十分に速いと言え、とくに最優先で工夫をする必要はなさそうです。
処理 | 処理時間 (ミリ秒) |
乗算 (AxB) | 1.6 |
除算 (A÷B) | 1.8 |
累乗 (A3) | 1.9 |
Int(1.23) | 1.5 |
算術計算の高速化については、計算式を簡単にして、算術演算の回数を減らすことがポイントになります。一例を挙げれば、自然数AからA+9 まで和を求めてBに代入する場合、
A+(A+1)+(A+2)+(A+3)+(A+4)+(A+5)+(A+6)+(A+7)+(A+8)+(A+9)→B
とするよりも、これを計算してしまって、
10A+45→B
とする方が、fx-5800P の Casio Basic では確実に速くなります。
以上の結果から、fx-5800P で 10ミリ秒や 20ミリ秒もかかる処理は、相対的にとても遅い処理なので、このような遅い処理をできるだけ使わないようにすれは、プログラム全体の処理が速くなることが分かります。
プログラムの高速化を試みる前に、実際に入力ボックスの応答性を比べるための評価用プログラムを作っておきましょう。
プログラム名: INBOX TEST
Norm 2
0→Z:0→S:0→T:0→U
Locate 1,1,"1:"
Locate 1,2,"2:"
Locate 1,3,"3:"
Lbl 0
-1→M
Do
Getkey→K
While K=0
K=35⇒1→M
K=36⇒2→M
K=37⇒3→M
Locate 1,4," " [スペース16個]
If M=1:Then
3→X:1→Y:10→D:2→E
Prog "INPI":Z→S
Else If M=2
Then
3→X:2→Y:10→D:2→E
Prog "INPI":Z→T
Else If M=3
Then
3→X:3→Y:10→D:2→E
Prog "INPI":Z→U
IfEnd:IfEnd
IfEnd
Locate 1,4,"Z="
Locate 3,4,Z
Goto 0
赤文字の INPI の部分は、応答性を比較するための実際のプログラム名が入ります。
なお、冒頭に Norm 2 があります。これは指数表示を行う条件を決めるコマンドです。Norm 1 とすると3桁以上になると指数表示され、Norm 2 にすると10桁以上になると指数表示されます。できるだけ指数表示されないようにしたいので、Norm 2としておきます。
Norm については、以下を参照。
⇒ Casio Basicコマンドリファレンス - Norm
Chapter 6-1
具体的に対処する遅い処理を見つける
Chapter 3 で作った INPI のプログラムを再度掲載します。
最初に作った INPI Ver 1.0 (プログラム名: INPI10)

キー入力の応答性を速くするのが目的なので、高速化対策が必要なのは、青文字で示した Lbl 0 と K≠47⇒Goto 0 で挟まれるループの内の処理です。入力ボックスが >>>> で表示された後、入力が完了して [EXE] キーを押すまで、このループが回ります。
ここで真っ先にに気がつくのは、赤文字で示した If 文、つまりテンキー入力部での条件判定部分です。この条件判定では、論理演算 (And と Or) が合計5個、そして比較演算子 (=、≦、≧) が合計7個使われています。このループ内全体では、論理演算が7回、比較演算が14回、配列変数 Z[ ] が使われています。
上記の、各コマンド・命令の処理時間の調査から、論理演算に約10ミリ秒、比較演算に約11.5ミリ秒かかることが分かっています。
遅 い 処 理 | 赤文字のIf文 | ループ全体 | |||
種別 | 時間 (ミリ秒) | 個数 | 時間 (ミリ秒) | 個数 | 時間 (ミリ秒) |
論理演算 | 10 | 6 | 60 | 7 | 70 |
比較演算 | 11.5 | 7 | 80.5 | 14 | 161 |
合 計 | 140.5 | 231 |
こうしてみると、この If 文の条件判定だけでも 140.5 ミリ秒、ループ全体の処理時間 231 ミリ秒のかなりの割合を占めていることが分かります。
この最初の INPI のファイル名を INPI10 としてください。次に倫理演算と比較演算を減らしたプログラムを作り、Ver 1.2 とし、プログラム名を INPI12 としてください。
INPI Ver 1.2 (プログラム名: INPI12)
Ver 1.0 に対して、変更した部分を赤文字で示します。

INPI Ver 1.2 のコードから、Lbl 0 ~ K≠47⇒Goto 0 のループ内にある、論理演算と比較演算の個数を調べて、Ver 1.0 と比較してまとめてみます。
Ver 1.0 (INPI10) | Ver 1.2 (INPI12) | |||
処理種別 (時間) | 個数 | 時間 (ミリ秒) | 個数 | 時間 (ミリ秒) |
論理演算 (10ミリ秒) | 7 | 70 | 3 | 30 |
比較演算 (11.5ミリ秒) | 14 | 161 | 9 | 103.5 |
合 計 | 231 | 133.5 |
この表から、If 文の条件判定の倫理演算と比較演算を減らすだけで、大幅な処理時間の低減が見込めます。
では、評価用プログラム INBOX TEST を以下のように変更して、実際に入力時の応答性を確認します。
プログラム名: INBOX TEST
0→Z:0→S:0→T:0→U
Locate 1,1,"1:"
Locate 1,2,"2:"
Locate 1,3,"3:"
Lbl 0
-1→M
Do:Getkey→K
While K=0
K=35⇒1→M
K=36⇒2→M
K=37⇒3→M
Locate 1,4," " [スペース16個]
If M=1:Then
3→X:1→Y:10→D:2→E
Prog "INPI10":Z→S
Else If M=2
Then
3→X:2→Y:10→D:2→E
Prog "INPI12":Z→T
Else If M=3
Then
3→X:3→Y:10→D:2→E
Prog "INPI":Z→U
IfEnd:IfEnd
IfEnd
Locate 1,4,"Z="
Locate 3,4,Z
Goto 0
INBOX TEST を起動すると、シンプルな画面を表示

入力すると、一番下の行に、変数Z の値が表示されます。

上記の評価プログラム INBOX TEST では、[1] キーを押せば INPI Ver 1.0 が呼び出され、[2] キーを押せば INPI Ver 1.2 が呼び出されます。実際に入力して、Ver 1.0 と Ver 1.2 を比較してみてください。応答性が改善されていることは体感できると思います。
実際に測定を試みる
タイマーソフトを使って、10 桁入力する時間を測定します。INPI は、Ver 1.0、Ver 1.2 ともにキーを押しっぱなしにすると、連続的に入力され、それが最も速い入力方法になります。そこで、INBOX TEST プログラムでは、青文字で示したように入力ボックスの桁数を 10 桁に設定します。
今回は、以下の Android スマホのアプリを使ってみました。iPhone 用も多くのものがあります。0.1秒の単位まで測定したいので、それより1桁多い 0.01秒まで表示のあるアプリで、評価の高いもの(=精度に問題ないだろうと言うもの)を選びました。
Android 用 Stopwatch and Timer
1) INBOX TEST を起動して、入力モードに入っておく。
2) タイマースタートと同時に、INBOX TEST で、どれかのキーを押し続ける。
3) 10 桁目が表示された瞬間に、タイマーを止める。
4) 測定を何度も繰り返して、同じタイミングで止める感覚をつかむ。
結果は以下の通り;
INPI バージョン | 10桁入力所用時間 | 1秒あたりの入力回数 |
1.0 | 2.8秒 | 3.5回 |
1.2 | 2.2秒 | 4.5回 |
この測定はとても個人差があるので、比較の意味しかありませんが、Ver 1.0 に対してVer 1.2 の応答性は、約 1.3倍程度向上しています。
Ver 1.2 への修正内容
Ver 1.0 から Ver 1.2 への変更について、修正部分は少ないのですが、念のために説明します。
Lbl 0 ~ K≠47⇒Goto 0 ループ内は、テンキーが押された時の処理を行う最初の If 文と部分と [DEL] キーが押されたの処理を行う Else If 文の部分で構成されています。今回の主な修正部分は、最初の If 文 の条件判定です。
ループに入ると、先ず最初に
Do
Getkey→K
LpWhile K=0
で、キーコードを取得して変数 K に代入しておきます。
そして、この K の値によって、テンキーか [DEL] キーかに応じて、最初の If 文か、次の Else If 文へ条件分岐され、それぞれの処理を行っています。
テンキーである [1] ~ [9] 、そして [0] のキーコードは、バラバラですので、これらの判定には論理演算と比較演算を多用する必要がありました。
さて、プログラム冒頭にある初期設定の部分では、配列変数を使ってテンキーの番号とキーコードを関連づけています。
1→Z[35]:2→Z[36]
3→Z[37]:4→Z[21]
5→Z[22]:6→Z[23]
7→Z[31]:8→Z[32]
9→Z[33]:0→Z[25]
これは、得られたキーコードからテンキーの数字を導くために必要なものです。キーコードが K に代入されているので、Z[K] は押されたテンキーの番号を与えます。
Ver 1.0 では、キーコード K を使って、押されたキーがテンキーかどうかを最初の If 文で判定しています。ここでは多くの論理演算と比較演算を使っています。
ところが、もし押されたテンキーの数字 Z[K] を使って、最初の If 文 での判定を行うと以下のようになり、論理演算と比較演算を大幅に減らすことができます。これが、 Ver 1.2 での応答性改善の基本的なアイディアです。
If Z[K]≧0 And Z[K]≦9
Ver 1.2 では、このアイディアに合わせて、いくつかの部分を修正しています。
配列変数の扱い
配列変数のアクセス(読み書き)には、20ミリ秒以上の時間がかかることが分かっています(上記の処理時間比較の実験による)。
⇒ fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較 (リンクを再掲)
配列変数をできるだけ使いたくないので、Z[K] を一旦通常変数、例えば I に代入しておき、
Z[K]→I
I を If 文の判定で使えば、配列変数 Z[K] の使用を1回に限定できます。
If I≧0 And I≦9
配列変数については、以下を参照。
⇒ Casio Basicコマンドリファレンス - 配列変数
通常変数 I の選定
通常変数に I を用いるには理由があります。変数 I は、ループの前と後(プログラムの頭の部分と最後の部分)で、For 文の制御変数としてのみ使われています。For 文の最初で変数 I は 1→I と初期化されます。つまり、I に何が代入されていても For 文の動作には全く影響がありません。つまり、I は使い捨て変数として自由に使えることから、テンキーの数を代入しておく変数として使えます。
INPI は、他のプログラムから呼び出して使うサブルーチンです。INPI で自由に多くの変数を使ってしまうと、呼び出すメインルーチンで使える変数に制限がかかります。言い換えれば、INPI では、できるだけ少ない変数を使い回しておく必要があるわけです。
入力数計算の変更
キー入力した数から、入力値(複数桁)を更新するための計算は、Ver 1.0 では以下のようにしています。
10Z+Z[K]→Z
Ver 1.2 では、Z[K] は I に置き換えて、読み出し時間が 20ミリ秒程度かかる配列変数を使わずに、
10Z+I→Z
と変更します。これによって、結果的に、Ver 1.0 も Ver 1.2 も ループ全体での配列変数アクセスの回数が1回に抑えられます。配列変数による処理速度の違いはありません。
Z[K]≧0 の問題
さて、If I≧0 And I≦9 の I≧0 は Z[K]≧0 と同じであり、実は、Z[K]≧0 には大きな問題があります。Z[K] が 0 (ゼロ) になるのは、[0] キーが押された時だけではありません。例えば Z[10] も 0 です。
テンキーの数とキーコードを関連付けるために Z[K] を使いますが、37→DimZ では、配列変数37個の領域確保を行い、領域確保を行うと、Z[1] ~ Z[37] までの全てが 0 で初期化されます。すると、テンキーを割り当てた10個以外の27個の Z[ ] には 0 が代入されています。
従って、 [0] キーを押した時の Z[25] 以外にも 0 になる Z[K] が多くあるので、[0] キーが押されていない時、例えば [X] 乗算キーが押された時は、キーコード K=24 なので Z[K] は 0 になります。すると、[0] キーが押されていないのに、最初の If 文 の処理が行われることになり、プログラムは誤動作します。
従って、[0] キーの判定は、キーの番号 Z[K]=0 つまり I=0 ではなくて、K=25 で判定する要があります。
以上の事情から、1つめの If 文は、以下のようにしておきます。
If (I≧1 And I≦9) Or K=25
0→Z[25] は不要
配列変数の領域確保を行ったところで、全ての配列変数は 0 で初期化されるので、配列変数が初期化された時点で Z[25] には 0 が代入されています。従って 0→Z[25] は不要です。これは、Ver 1.0 でもそうなのですが、以前は気がつきませんでした。配列変数への書き込みは 20ミリ秒程度の時間がかかります。0→Z[25] を省略しても、今回の目的である入力応答を速くする効果はありませんが、入力ボックスが呼びだされてから入力ボックスに入力できるようになるまでの時間短縮には役立ちます。
そこで、Ver 1.2 では 配列変数初期化の部分から、0→Z[25] を削除することにします。
配列変数の領域確保の問題
変数 I を判定で使うために、Z[K]→I とする部分に、もう一度着目します。配列変数の領域確保で、37→DimZ とすると、キーコードが 37 より大きい場合は、Z[K]→I でエラーが発生します。
プログラムを使っていて、テンキーと [DEL] キー以外のキーを押してしまうことは普通にあります。キーコードが 37 よりも大きくなるキーが押されると、どうなるでしょうか?
37→DimZ が実行されたときのメモリ内の様子
・・・ | ・・・ | Z[1] | Z[2] | ・・・ | Z[36] | Z[37] | ・・・ | ・・・ |
配列変数の領域確保とは、電卓のメモリの中で、配列変数のために使えるメモリを確保することです。37→DimZ を実行すると、メモリの中から37個分の領域を確保し、全てに 0 を代入します。
この時、例えば [RCL] キーを押すと(キーコード 41)、K に 41 が代入され、次に Z[41]→I が実行されると、Z[41] から値を読みだそうとします。ところが、メモリには Z[41] は確保されていないので、エラーとなるわけです。
このエラーを回避するには、十分な領域を確保しておけば良いことが分かります。fx-5800P のキーコードで一番大きい値は 87 です。取扱説明書の99ページに、キーコードの説明があり、そこで分かります。或いはキーコード取得プログラムで実際にキーコードを調べて見ると、キーの配置とキーコードには一定の規則があって、 [▶] キーが最大の 87 を返すことが分かります。
⇒ プログラムライブラリ - キーコード取得
配列変数の領域は、いくらでも確保できます(使えるメモリが残っている限り)。配列変数が使うメモリ領域とプログラムを格納しているメモリ領域は共用されるので、多くのプログラムを保存していると、その分使える配列変数の領域が減ります。いずれにせよ、配列変数は必要なだけ確保し、プログラム終了時には解放しておく必要があります。解放しなければ、メモリの無駄食いになり、保存できるプログラムが減ります。
そこで、Ver 1.0 では 37→DimZ としていましたが、Ver 1.2 では 87→DimZ と変更します。
Ver 1.2 が完成しました。
さて、1つめの If (I≧1 And I≦9) Or K=25 内の処理には、以下のコードが含まれています。
C≠1 Or A≠25⇒Isz X
C=1⇒K→A
ここで、論理演算が1回、比較演算が3回使われているので、目安として44.5ミリ秒程度かかることになります。ここから、できるだけ 論理演算と比較演算を減らせば、さらに高速化できそうです。
実のところ、小数対応するために拡張すると、この部分はさらに複雑な処理になり、より多くの論理演算と比較演算が必要になっている、と言う事情もあります。
そこで、次回では、この部分の処理を見直す予定です。
つづく...
⇒ Casio Basic入門33 / 目次
応援クリックをお願いします。励みになるので...
- 関連記事
-
-
Casio Basic入門38 2015/02/11
-
Casio Basic入門39 2015/02/06
-
Casio Basic入門32 2015/01/25
-
Casio Basic入門37 2015/01/23
-
Casio Basic入門36 2015/01/15
-