Casio Basic入門38

Casio Basic(超)入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します

最終: 2015/02/11


 4. CasioBasicを使ってみる(続き)

前回: Casio Basic入門37 - Chapter 6 を見る


Chapter 7  - 初級

今回は、初めて fx-58800P でプログラムを作ってみる想定で、プログラミングに必要な fx-5800P の操作方法を具体的に説明し、シンプルなプログラムを作り、それを徐々に改造してゆくことにします。

プログラミング経験が少ない場合は、先ずCasio Basic入門1の 2. プログラミングとは? から Chapter 0 までに目を通してください。
 ⇒ Caso Basic入門1 - 2. プログラミングとは?: プログラムの基本的な考え方
 ⇒ Caso Basic入門2 - Chapter 0: プログラム作成・実行のポイント


Chapter 7 の流れとポイント

以下の流れで、初めて作る最もシンプルな電卓プログラムを徐々に改造してゆきます。
 1) 最もシンプルなプログラム1: 入力計算出力
 2) 最もシンプルなプログラム2: 同じプログラム構成で別のプログラム作成
 3) メニューでプログラムの切替え: メニューで最もシンプルなプログラム1と2を選択して実行する
 4) メニュを3つに増やす: 最もシンプルなプログラム3つを切り替える
 5) メニュー選択の改良: 想定外の使用方法への対策
 6) メニュー表示の改良: メニュー画面と出力画面の統一によるプログラム効率化


◆ Chapter 7 の目標: ゼロからのプログラム作成と機能追加

fx-5800P のようなプログラム電卓で作る代表的なプログラムは、次のようなものでしょう;

1) 入力: 数値を入力させ
2) 計算: 計算して
3) 出力: 結果を表示する

そこで、今回は温度換算プログラムを題材にして、Caso Basic 入門レベルから始めて、徐々に改造してグレードアップし、最後は入力ボックスを活用してみます。



温度換算プログラムを作る前に - 摂氏と華氏

温度が30度と言う時、普通の日本人では、セッシ(摂氏)温度、°C を暗黙の了解で使っています。

一方、アメリカでは違った温度の単位を使っています。夏の気温が 90 度、などと言うので、アメリカに旅行したことのある方は、一度は驚いた経験があると思います。この 90 度は、おおよそ日本の 32 度と同じです。つまり、使っている単位が違っているのです。アメリカでは、カシ(華氏)温度を使っていて、°F と言う単位を使っています。但し暗黙の了解があるので、F を省いて 90° とだけ表示することもあります。

ちなみに、摂氏温度の °C は、セルシウス (Celsius) の C が由来です。華氏温度の °F は、ファーレンハイト (Fahrenheit) の F が由来です。摂氏や華氏と言う日本語は、これらの温度単位を提唱した人の名前の音読みを中国語で表現して、最初の漢字に人物を意味する氏を付けたもので、それが輸入されて日本でも使っているようです。

アメリカ旅行中に突然熱がでて、とりあえず病院に行って、熱が38度あります、と言うと、アメリカ人看護師や医師は一瞬??と思うでしょう。アメリカで38度は、華氏38度で、これは摂氏3.3度ですから...(^^;)

熱で朦朧としているのに、計算なんかできません。そこで電卓プログラムの登場...ちょっと苦しいこじつけですが、摂氏温度を華氏温度に換算するプログラムを作ってみましょう。



Chapter 7-1
摂氏から華氏への換算プログラム


プログラム作成の準備

Chapter 0 を参考にして、fx-5800P で、プログラム名 TC1 で新規プログラムを作ります。

まず、[AC] で fx-5800P の電源を入れましょう。普通の電卓の画面が表示されます。COMPモードと言います。

Compモード 

ここで、[MODE] キーを押すと、モード選択メニューが表示されます。

Modeメニュー 

[1] 1:COMP を選ぶと、普通の電卓画面(COMPモード)に戻ります。

ここで、[5] 5:PROG を選ぶと、プログラムモード(PROGモード)に進み、Program Menu が表示されます。

Program Menu 


電源を入れた時、普通の電卓の画面以外が表示された場合は、[MODE] キーでモード選択メニューに切り替え、[5] (5:PROG)でProgram Menu に切り替えます。

Program Menu 

これで、プログラム入力の準備ができました。



プログラムファイル作成

Program Menu 

Program Menu で [1] (1:NEW) を選び、ファイル名入力画面に切り替えます。

File Name 1 

ここで、プログラム名 TC1 を入力します。File Name? では、最初はアルファベットモードになっています。画面上部に A アイコンが表示されているので、アルファベットモードだと分かります。ここで、[2] (T) [°’”] (C) と入力した後、[ALPHA] を押してアルファベットモードを解除し、[1] を入力します。

File Name 2 

そして、 [EXE] で確定します。


すると、File Mode 画面に切り替わります。

File Mode 

ここで、 [1] (1:COMP) を選びます。

すると、何も表示のない画面に切り替わります。画面上に PRGM と表示されていて、この画面でプログラムの入力や編集を行います。

Program Input 


プログラムの入力

プログラム編集画面で、以下のプログラムを入力してください。

"°C"?C
(9÷5)C+32


1行目を入力したら、[EXE] キーを押して改行し、2行目の入力を始めます。

このプログラムでは、1行目にあるがポイントです。はたった1文字ですが多彩な機能を持った「入力命令」です。
詳しくは後で説明しますが、数値をキー入力させそれを変数に代入することができます。?(入力)命令には、主に以下の機能が含まれています。
 ・代入する変数に格納されている値を入力前に表示
 ・数値の入力
 ・入力数値の編集
 ・入力確定
 ・確定入力値の表示
 ・確定入力値の変数への代入

?(入力)命令は、シンプルな1文字ですが、機能が満載です。

注) fx-9860GII や fx-CG20 でこのプログラムを入力する場合は、? が使えないので、代わりに ?→ を使ってください。fx-5800P の入力命令には、 ??→ の2つが用意されています。一方で、fx-9860GII / fx-CG20 では、入力命令 ? は使えず、?→ のみが用意されています。但し、??→ では動作が少し異なります(その違いは後で説明しています)。


なお、(入力)命令の前に、"°C" があります。出力命令 " " を使っています。" で挟まれた文字列を表示する動作をします。

さて、実際のプログラム入力について、簡単な説明をします。

先ず最初に、" を入力するには、
[ALPHA} [√□] ("
の順に入力します。

次に、°C° を入力するには、

[FUNCTION] キー
[5] キーで 5:ANGLE 選択
[1] キーで 1:° 選択

の順に入力します。

[FUNCTON] キーで FUNCTIONメニューが表示され、

Functionメニュー 

ここで、[5] (5:ANGLE) を選ぶと、ANGLEメニューが現れます。

Angleメニュー 

[1] (1:°) を選ぶと、° を入力できます。


次に、C を入力するには、
[ALPHA] [°’”] (C) 
の順に入力します。


?命令を入力するには、

[FUNCTION] [3] (3:PROG) [1] (1:?)

の順に入力します。


アルファベットを入力する時は、[ALPHA] に続いて 赤い印字のアルファベットのキーを押します。

TC1_Source 

1行目の最後に改行マーク が入っています。

上の2行のプログラムを入力し終わったら、[EXIT] キーを押します。すると、Prog Edit 画面に切り替わります。

Prog Edit 

ここで、TC1 にカーソルがきているので、[EXE] を押せば、再びプログラム編集画面になります。

プログラム編集画面で、[EXIT] キーを押して、Progra Edit 画面に戻ります。

Prog Edit でさらに [EXIT] キーを押すと、Program Menu 画面に戻ります。今どこに居るのか分からなくなったら、[EXIT] を何度か押せば、最後には Program Menu 画面に戻ります。

Program Menu 


作ったプログラムの実行

さて、今入力したプログラムを実行しましょう。

Program Menu 

Program Manu 画面で、[2] (2:RUN) を選ぶと、Prog List 画面に切り替わります。

ProgList2 

ここで、実行したいプログラム TC1 を矢印キー [▼][▲] で選んで、[EXE] キーを押せば、そのプログラムが実行されます。

では、実行しましょう。

TC1-1 

2行目の右端に何か数字が表示されていると思います(後で説明します)。ここで、38 と入力しましょう。

TC1-2 

この入力を確定するために [EXE] を押すと、右下に 100.4 と表示されました。これが華氏温度です。

TC1-3 

このプログラム TC1 は、°C? と表示された時に摂氏温度を入力すれば、華氏温度を表示します。出力は行の右端に表示され、入力した数値は行の左端に表示されるので、分かりやすいですね。これも?(入力)命令の仕様です。

ここで、[EXE] を押すとプログラムが終了して、Prog List  画面に戻ります。

ProgList3 

プログラムを編集するには、ここで [EXIT] を押し、Progrm Menu画面に戻ります。

Program Menu 


プログラム動作が異常のとき

プログラムの動作が期待された通りでない場合は、プログラムの入力ミスやバグの可能性が殆どです。

入力ミスやバグのために、エラー表示が現れることがあります。例えば、Syntax ERROR は文法上の誤りを意味します。

 SyntaxERROR 

エラーの種類については、fx-5800P 取扱説明書の111ページにある一覧表が示すように、様々ななものがあり、エラーの原因を推定できます。エラー表示が現れた時、[EXIT] を押すと、プログラム編集画面に戻り、エラーの原因となった部分の直後にカーソルが表示されます。以下は Syntax ERROR が起こるプログラムの一例です。

Bug 2 

この場合、一行目を本来 "°C"?C とすべきところ、最後の C の入力時に、[ALPHA] キーを押さずに [°’”] を押してしまったケースです。変数でない記号が入力されているので、?命令による代入が正しく行われないのが問題です。エラーの原因となる記号の直後にカーソルがきています。これを修正し、[EXIT]Prog Edit 画面に戻ります。

Prog List (PROG MODE) 3 


プログラム実行中に強制終了させて、プログラムを編集しなおすこともできます。プログラムを強制終了するには、[AC] キーを押します。すると、AC でプログラムが中断されたと言う AC Break 画面に切り替わります。

AC Break 

ここで、表示に従って [EXIT] を押すと、プログラム編集画面に戻ります。

TC1_Source 

プログラム編集画面で、もう一度 [EXIT] を押すと、Program Menu 画面に戻ります。


もう1つのプログラム実行方法 - COMPモードからのプログラム実行

[EXIT] キーを連打して、Program Menu 画面に戻りましょう。

Program Menu 

そして、[MODE] [1] (1:COMP) の順に押して、COMPモード(普通の電卓の画面)に戻します。

Compモード 

ここで、[FILE] キーを押すと、Prog List 画面に切り替わります。

Prog List 

COMPモード(普通の電卓の画面)から、[FILE] 一発で Prog List  を表示できるのは、fx-5800P と fx-FD10 Pro のみです。他のグラフ関数電卓では、この便利な機能がありません。

この画面をよく見てみると、画面上部に PRGM の表示がありません。つまり PROGモード ではなく、COMPモード であることを示しています。

さて、Prog List 画面では、自動的にアルファベットモードになっています。画面の左上に小さな A アイコンが表示されているので、アルファベットモードであることが分かります。ここで、[2] (T) を押すと、T で始まるプログラム名の最初のプログラムが一番上に表示され、カーソルが乗っています。もし T で始まるプログラムがなければ、アルファベット順で T の次で始まるプログラムが一番上に表示されます。既に TC1 を作っているので、TC1 にカーソルを合わせてから [EXE] キーを押すと、TC1 が起動されます。

TC1-1 

ここで、摂氏温度 38 を入力し、
 
TC1-2 

[EXE] で入力確定すると、華氏温度が表示されます。

TC1-3 

ここまでは、上記の PROGモード での動作と同じです。

再度 [EXE] を押すとプログラムが終了しますが、今回は Prog List が表示されずに、プログラム TC1 が再度起動します。

TC1-4 

これが、COMPモード[FILE] キーによる Prog List 利用の面白いところで、実用上の利便性が考慮されています。

プログラムが終わっても同じプログラムが再起動するので、何度でも温度換算を繰り返せますね。プログラムを終了させるには [AC] キーを押します。[FILE] キーからのプログラム起動のメリットが、ここにもあります。fx-5800P では、このような利便性が考えられているのです。

実は、COMPモードProg List からプログラムを実行するのは、COMPモード

Prog "TC1"

と入力して [EXE] を押すのと全く同等です。fx-5800P では、COMPモードから Prog コマンドを使ってプログラムを実行できるようになっていて、それを補助するのが [FILE] キーによる Prog List 表示機能なのです。

たった2行で実用的なプログラムができました。これは、Casio Basic で作る最もシンプルなプログラムだと思います。


2つのプログラム実行方法の使い分け

以上みてきたように、fx-5800P では、プログラムを実行するために2つの方法が提供されています。プログラムを編集したり変更する際は、Program Menu から実行するのが良いのですが、一旦完成したプログラムを実行するには、COMPモードから [FILE] キーを使って実行する方が良いでしょう。と言うのも、COMPモードから実行すると、プログラムをうっかり変更してしまう危険性が無いからです。

COMPモードで [FILE] キーを押した時に現れるプログラムリストは、よく使うプログラムを最大5つまでリストの先頭に表示させる機能もあります。⇒ 取扱説明書 92ページ 「プログラムを「お気に入り」登録するには」を参照

一方、fx-9860GII や fx-CG20/10 では、プログラムを実行するためには Programモードの Program List から実行するしかありません。


プログラムの説明

今回作ったのは、Casio Basic で作る最もシンプルなプログラムだと思います。ここで使ったのは、" " (出力)命令 ?(入力)命令だけです。
 ⇒ Casio Basic コマンドリファレンス - " " (出力)命令
 ⇒ Casio Basic コマンドリファレンス - ?(入力)命令

?(入力)命令には、多彩な機能が隠されています。

?命令の書式は、

?[変数]

変数に C を使って、

?C

とすると、画面の左端にとだけ表示され、プログラムの動作が一旦停止し、入力待ちになります。

プログラミングで知っておくべき最も大切な基本の1つが、プログラムは特に何も命令されなければ、上から下へ止まらず連続的に動作し続けると言うことです。Casio Basic のプログラミングでは、この原則に従って、上から下へ命令やコマンドを書いてゆきます。

入力命令?には、この原則を破って、一旦停止して入力待ちを行う機能があると理解してください。一旦停止した状態を解除するには、[EXE] キーを押して入力を確定します。すると確定された入力値が変数 C に 代入 されます。これは?命令の仕様です。


代入とは?
変数とは、数値を入れる容器です。そして容器には名前が付いていて区別できるようになっています。変数 C は 容器 C というわけです。容器 C に数値を入れることを、変数 C に数値を代入する、と言います。代入と言う表現以外にも、C に数値を入れる / 格納する、などともいいます。要するに、名前のついた容器に数値を入れると言う感覚に基づく表現です。


さて、?命令には、次のような書式もあります。

"文字列"?[変数]

文字列を " " で囲むと、ここで指定した文字列表示してから、一旦停止して入力待ちになります。Casioのプログラム電卓では数字と英語のアルファベットそして一部の特殊記号を文字列に使えますが、残念ながら日本語の文字は使えません。何か表示するには、ローマ字表現か英語表現を使うことになります。


例えば、

"INPUT"?C

と書いて実行させると、

画面の左端に、

INPUT?

と表示され、プログラムが一旦停止して、入力待ちになります。

そして、数値を入力して [EXE] で入力を確定すると、入力した数値が変数 C に代入されます。この C は2行目の計算で使います。

つまり、入力命令?には、以下の機能が備わっています。
1) プログラムを一旦停止して入力待ちする
2) [EXE] で入力を確定する
3) 確定した入力値を変数に代入する

今回のプログラムでは、摂氏温度を入力するので、分かりやすくするために、

"°C"?C

と書いています。これが実行されると、画面の左端に

°C?

と表示されます。但し、1行下の右端にも数値が表示されていると思います。これも?命令の仕様です。

TC1-1 

変数 C に既に格納されている値が表示されています。COMPモード[FILE] キーを押して現れる Prog List から TC1 を実行すると、既に説明したように、プログラムが終了しても自動的に再起動するので、次々に異なる温度を入力できて便利です。すると前回代入された C の値が表示されると、[EXE] を押すだけで、同じ値を入力確定できますので、プログラムによってはとても便利です。

もし、前回代入された値を表示させたくない時は、以下のような書式も使えます。

"文字列"?→[変数]

今回のプログラムで、変数 C に格納されている値をいちいち表示させずに、毎回値を新たに入力させるようにするには、

"°C"?→C

のように、?の後ろに を追加します。このように、

たった1文字の?命令には、極めて多彩な機能が備わっていることを紹介してきました。入力命令?には、既にお気づきのように、何かアクションをするたびに自動的に改行する機能も備わっています。4行目で改行すると画面が自動的にスクロールします。次々に様々な値を入力させ、最後に計算をして結果を表示させるプログラムを非常に簡単に作ることができます。



では、2行目の (9÷5)C+32 について見てゆきます。1行目で、入力した摂氏温度が変数 C に代入されていて、この C に入っている数値を使って、2行目の計算を行って、華氏温度を求めています。

例えば、摂氏温度 38 ℃ の時、この計算の結果は 100.4 となります。

Casio Basic は、プログラムの最後に計算式があると、プログラム終了時にその計算結果を表示する、という仕様になっています。今回のプログラムは、この仕様を利用しています。


今回のプログラムは、摂氏温度から華氏温度を計算して表示するものです。逆に華氏温度から摂氏温度を求めるプログラムも殆ど同じようにして作れると思います。

摂氏温度を C、華氏温度を F とすると、今回使った計算は

F=(9÷5)C+32

この式を普通の数学を使って変形すると、

C=5(F-32)÷9

となりますね。


では、今回とは逆の換算、つまり 華氏温度を入力して摂氏温度を表示するプログラムを次回までに作ってみてください。




つづく...

Casio Basic入門39 / 目次




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

 


keywords: fx-5800PCasioBasic、入力ボックス, プログラミング入門プログラム関数電卓、温度換算

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Basic入門の記事のチェック

お知らせ

Casio Basic 入門の過去の記事を最初から読み直して、分かりにくい表現や記載ミスがあれば、順次修正を行っています。

掲載しているプログラムは、全て実際に実行して確認した内容を記載しているのですが、記載ミスがあれば意味がありません。これまでもミスを見つけた時は随時修正してきましたが、改めて最初からじっくりと読み直して、記事のデバッグを行うことにしました。

さらに、新製品の登場や、fx-9860GII を入手して確認したことなど、更新すべき内容についても、合わせて修正します。

大きな修正を行った時はこれまでのように、記事の冒頭右側修正日を記載します。合わせて、常にトップに表示されるページで、チェックの進み具合をお知らせします。




[2015/01/30 追記]
現在公開している最新のエントリー Caso Basic入門37 までチェックが終わっています。プログラムコードの記載ミス、説明の抜け、混乱させる間違った説明が見つかりました。これらは全て修正しています。




管理人: Krtyski (やす)
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Basic入門37

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します

修正:2015/01/25


 4. CasioBasicを使ってみる(続き)

Chapter 6

前回: Casio Basic入門36 を見る


◆ Chapter 6 の目標: プログラムを速くする
入力ボックスの改良と拡張

入力ボックス2.0 にバージョンアップして、ようやくfx-5800P Casio Basic でストレスなく使えるようになりました。この汎用サブルーチンは、より画面の広い fx-9860GII ではさらに役立つので、今回は入力ボックス を fx-9850GII に移植します。



Chapter6-7
fx-5800P から fx-9860GII へ移植する

高速動作する fx-9860GII では、キーリピート対策が必要です。そこで、この対策を行った fx-5800P 用 IN Ver 2.1 のプログラム(以下)を元に移植を進めます。

[2015/01/25 修正] INPI Ver 2.0 のコードを掲載していたのを正しく IN Ver 2.0 に修正しました。

INv20src1_fx-5800P 


プログラム構造

[初期表示と変数の初期化]

[キー入力]

[後処理]


このプログラムをそのまま fx-9860GII で動作させても、以下の理由からエラーになります。

1. fx-9860GII には配列変数がない
2. fx-9860GII では、Getkey が返すキーコードが異なる

さらに、fx-9860GII の広い画面を活かすために、Locate の引数を最適なものに変更した方が良いでしょう。



fx-9860GII Casio Basic での配列

fx-5800P の配列変数 Z[ ] は fx-9860GII の Casio Basic には準備されていません。配列変数の代わりとして使えそうなのは、行列とリストです。

以前、fx-9860GII (ノーマルクロック 29MHz) で行列とリストのアクセス速度を測定しています。結果の表を再掲載します。
 ⇒ fx-9860GII への移植 - ピタゴラス数

表 行列とリストのアクセス速度
処理内容処理時間 (ミリ秒)
リスト読み出し13.2
リスト書き込み17.6
行列読み出し10.7
行列書く込み12.0

明かに行列の方がアクセス速度が速いので、配列変数の代わりに行列を採用します。

さて配列変数は、1行K列の行列と同じなので、87個の配列変数Z[K] を1行87列の行列 Z[1,K] に置き換えます。ここで、K は1~87の整数です。


この行列 Z の領域確保は、{1,87}→Dim Mat Z

そして、配列変数 Z[K] の代わりに、行列 Mat Z[1,K] で各要素にアクセスします。
例えば、数 1 を、1行72列目の要素に代入する場合は、

1→Mat Z[1,72]

とします。


異なるキーコードの対応

同じキーを押しても Getkey が返すキーコードは、fx-9860GII と fx-5800P で異なります。キーコードを知るには、取扱説明書を見るか、キーコード取得プログラムを実行してください。

取扱説明書キーコード取得プログラム
fx-5800P99 ページプログラムライブラリ - キーコード取得
fx-9860GII8-17 ページ

入力ボックス IN Ver 2.1 で使うキーコードをまとめます。

キーfx-5800Pfx-9860GII
1 (テンキー)3572
2 (テンキー)3663
3 (テンキー)3752
4 (テンキー)2173
5 (テンキー)2263
6 (テンキー)2353
7 (テンキー)3174
8 (テンキー)3264
9 (テンキー)3354
・ (小数点)2661
DEL3444
(-) (負号)5741
- (減算記号)6732
その他 [AC] 以外のキー・・・・・・
キーコード最大値8779
入力ボックスで使うキーだけを具体的に示していますが、他のキーのキーコードも異なります。



これに基づき、行列の領域確保と初期化は、以下のようになります。

なお、fx-9860GII ではキーコードの最大値が 79 になっていることに留意します。行列の領域確保はその分メモリを消費するので、必要最小限にすべきです。

{1,79}→Dim Mat Z
1→Mat Z[1,72]
2→Mat Z[1,62]
3→Mar Z[1,52]
4→Mat Z[1,73]
5→Mat Z[1,63]
6→Mat Z[1,53]
7→Mat Z[1,74]
8→Mat Z[1,64]
9→Mat Z[1,54]



初期表示と変数の初期化

fx-9860GII 用に書き直すために、キーコードの扱いを変更し、配列変数を行列に切り替えましたが、最後に Locate コマンドを使った画面表示を変更します。入力ボックス・インジーケータは、画面の右下の端に表示するのが良いので、それに併せて表示位置を変更します。なお、fx-9860GII では小文字アルファベットや特殊記号 などが文字として使えるので、それを利用します。

If E=2:Then
Locate 11,7,"<EXE>:Enter"
Else If E=1:Then

Locate 20,7,"▶E"
IfEnd:IfEnd
E→Mat Z[1,1]
For 1→I To D
Locate X+I-1,Y,">"
Next
0→C:0→F:1→E



キー入力ループ

キーコードが異なる以外は、fx-5800P のプログラムと全く同じになります。fx-5800P と異なる部分を青文字で示します。同じ Casio Basic なので移植性は高いようです。

但し、fx-9860GII は、fx-5800P に比べると処理速度が格段に速く、キーリピートが頻発して使いにくいので、以下の赤文字の部分でキーリピートを抑制しています。

 ⇒ キーリピート抑制 - 逆引き Casio Basic

Do

While Getkey
WhileEnd


Do
Getkey→K
LpWhile K=0
Mat Z[1,K]→I

If (I≧1 And I≦9) Or K=71
Then
If C<D:Then
If F:Then
Z+EI÷10^(F)→Z
Isz F
Else
10Z+EI→Z
IfEnd
Locate X+C,Y,I
Isz C
IfEnd

Else If K=61
Then
If F=0:Then
Locate X+C,Y,"."
Isz C:Isz F
IfEnd

Else If K=44
Then
If C:Then
If F:Then
F-1→F
F⇒Int(10^(F-1)Z)÷10^(F-1)→Z
Else
Int(Z÷10)→Z
IfEnd
C-1→C
C=0⇒1→E
Locate X+C,Y,">"
IfEnd

Else If K=32 Or K=41
Then
If C=0:Then
Locate X,Y,"-"
-1→E:Isz C
IfEnd
IfEnd:IfEnd
IfEnd:IfEnd

LpWhile K≠
31




行列利用の後処理

fx-5800P と殆ど変わりません。fx-5800P では 配列変数の領域解放を行っているので、配列変数の代わりに使った行列も領域解放を忘れずに行います。これをやらないと、メモリが占有されたままになって、使えるメモリが減ってしまいますので要注意です。行列の領域解放には ClrMat コマンドを使います。変更部分を青文字で示します。


For 1→I To D-C
Locate X+C+I-1,Y," "
Next
Mat Z[1,1]→E
If E=2:Then
Locate 11,7,"      "
Else If E=1:Then
Locate 20,7,"  "
IfEnd:IfEnd
ClrMat
Return


これで、IN の移植が終わりました。ここで行った変更は、INPINPI にもそのまま適用できます。

なお、移植したプログラムのプログラム名は、fx-5800P 向けと同様に、それぞれ INPIINPIN としておきます。



プログラム

fx-9860GII (及び fx-CG20) は、プログラムを入力せずに、ファイルをダウンロードして電卓に転送するだけでプログラムを利用できます。プログラムファイルのダウンロードはプログラムライブラリからできます。
 ⇒ 入力ボックス 2.1G - fx-9860GII & fx-G20専用

IN Ver 2.1G for fx-9860GII

IN Ver2.1G for fx-9860GII 


INP Ver 2.1G for fx-9850GII

INP Ver2.1G for fx-9860GII 


INPI Ver 2.1G for fx-9860GII

INPI Ver2.1G for fx-9860GII 


処理能力の高い fx-9860GII では、入力速度の問題は全くありません。



さて、処理速度の遅い fx-5800P でも実用的な応答性で動作する入力ボックス2.0 /2.1 が出来たので、次々回 Chapter 8入力ボックス2.0 /2.1 (好みの方を使って下さい)を使って、初級者向けの簡単なプログラムを作ってみます。

次回 Chapter 7 では、Casio Basic(超)入門編 として、Casio プログラム電卓で作れる、最も簡単なプログラムの作り方を紹介します。この最も簡単に作れるプログラムを出発点として、Casio Basic を駆使した高品質なプログラムへの改造方法を Chapter 8 で行います。



つづく...

Casio Basic入門38 / 目次




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

 


keywords: fx-5800PCasioBasic、入力ボックス, プログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Basic入門36

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します

修正: 2015/01/25


 4. CasioBasicを使ってみる(続き)

Chapter 6

前回: Casio Basic入門35 を見る


◆ Chapter 6 の目標: プログラムを速くする
入力ボックスの改良と拡張

前回は、IN Ver 2.0  を作り、入力ボックス 2.0 が一通り揃いました。

本ブログの読者の方から、応答性が大幅に向上した一方で、「ちょっと油断してキーを離すのが遅れると、数字がリピートしてしまう」というご報告を頂きました。

応答速度を測定するためにキーを押しっぱなしにして測定しました。つまりキーを長押しすれば数字がリピートするのは、プログラムの仕様としてそのように作ったので、仕様通りの動作と言えます。

電卓としてのハードウェア仕様は、長押しで数字はリピートしません。PCでは一定時間を超えて長押しするとキーリピートが発生する仕様になっています。

入力ボックス 2.0 がキーリピートするものの、チャッチャとキーを押せばそれほど問題なく入力できるのは、たまたま fx-5800P の動作が遅いことが理由です。実は、このプログラムを 動作の速い高機能グラフ関数電卓 fx-9860GII に移植すると、チャッチャとキーを押してもキーリピートが頻発して、とても使いにくくなります。

つまり、fx-5800P 用としては結果オーライですが、プログラムとしては不完全と言うこともできます。もし、応答性に影響を与えずにキーリピートを防止できれば、その方が良いプログラムです。

そこで、今回はキーリピート対策を施した 入力ボックス 2.1 を作ります。



Chapter6-5
キーリピートを抑制する

キーリピートが発生する原因が分かれば、対処方法も分かります。

キー入力ループ内で、以下のようにキーコードを取得しています。

Do

Do
Getkey→K
LpWhile K=0


・・・・・

LpWhile K≠47


外側の Do ループの中に、もう一つの Do ループが入っています。


[EXE] キーで入力確定を行わない限り([AC]キーは除く)、この外側の Do ~ LpWhile K≠47 ループの中で処理が繰り返されます。

何かキーを押すと、内側の Do ~ LpWhile K=0 ループでキーコードを取得してスグにループを抜けます。もし、キーを押しっぱなしにすると、内側のループはキーコード取得後1回で通り抜け、押されたキーを出力する処理が繰り返し続くので (外側のループの働きによる)、同じキーがリピートして表示されます。これが、キーリピートの原因です。

ならば、キーリピートを抑制するために、内側の Do ループに入る前に、キーを離さないと先に進めない(つまり、キー取得処理を行う Do ループに入れない)ようなゲート(関所)を設ければ良いわけです。

そこで、内側の Do ループの上に、以下の2行を追加してみます。この2行でループになってます。

While Getkey
WhileEnd


Getkey コマンドは、キーが離されている時は 0 を返し、キーが押されていると 0 以外のキーコードを返します。この2行のプログラムは、Getkey が実行される時に何かキーが押されていると0 以外を返すので「真」となりループを継続します。Getkey が実行される時キーが離されていると、0 を返すので「偽」となり、ループを終了します。すると次へ進めます。つまり、キーを離さないと先に進めないゲートの役割を果たします。

ここで、While [ループ継続条件] の書式では、[ループ継続条件] が 「真」か「偽」かで判定します。戻り値のあるコマンド Getkey をこのような記法で使うと、戻り値が 0 ならば「偽」、0 以外なら「真」と判定されることを思い出して下さい。
 ⇒ Casio Basic コマンドリファレンス - While 文

Do

While Getkey
WhileEnd


Do
Getkey→K
LpWhile K=0


・・・・・

LpWhile K≠47


この僅か2行のコードで応答速度にどの程度影響があるかは、実際にプログラムを走らせて確認します。

キーリピート抑制機能を盛り込んだものを入力ボックス 2.1 とします。プログラムをまとめて以下に掲載します。

さて、INBOX TEST から呼び出して使ってみると、INPI 2.1 はキーリピートを抑制しても、応答性が悪くなる感覚が殆どないと思います。一方、INP 2.1IN 2.1 はどうしても応答性が悪くなるようです。

そこで、私は INPI 2.1INP 2.0IN 2.0 の組み合わせで使うことにします。ゆっくりとキー入力する方なら全て 2.1 でも良いかも知れません。好みに合わせてうまく使い分けて下さい。



キーリピート抑制機能付きの 入力ボックス 2.1INPI Ver 2.1INP Ver 2.1IN Ver 2.1 は以下のようになります。

INPI Ver 2.1

INPI Ver2.1 for fx-5800P 


INP Ver 2.1

INP Ver 2.1 for fx-5800P 


IN Ver 2.1

IN Ver 2.1 for fx-5800P 



入力ボックス2.1 は便利なので、次回は fx-9860GII への移植を行います。私には入力ボックスは不可欠なサブルーチンになっています。



つづく...

Casio Basic入門37 / 目次




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



カシオプログラム関数電卓 FX-5800P-N カシオプログラム関数電卓 FX-5800P-N
(2006/09/22)
CASIO(カシオ)

商品詳細を見る



keywords: fx-5800PCasioBasic、入力ボックス, プログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

楽屋裏 - Casio Basic プログラミング

楽 屋 裏
e-Gadget


出来の悪い入力ボックスを、なんとかしたいと思ってから結構時間がかかってしまいました。まともに使えるものが出来て、それをほぼ公開するところまできて、実はホッとしています。

日頃から、いろいろと触って気がついたこと、チョット深掘りしてみたいことは結構あるのですが、いざ深く調べて見ると、色々なことが分かって、結構面白いものです。

Casio のプログラム電卓のプログラミングについて書かれているブログやホームページを拝見していると、Casio Basic 特有の出力命令や出力命令、そして Goto 文を多用したものが多いように感じるのは私だけでしょうか?

せっかく Casio Basic が進化しているのに、それにふさわしい使い方をしてあげて欲しいと思うわけです。昔から電卓でプログラミングをなさってきた方は、その時の流儀があって、そのまま適用してプログラムをかけてしまうのも、Casio Basic の素晴らしいところだと思います。是非とも、本格的な構造化Basicとして Casio Basic ならではの構造化プログラミングを採用して頂きたいと思います。

Casio Basicならでは、と言うのは、例外処理では Goto 文が有効だからです。

最近、fx-9860GII で色々とプログラムを作ってみていますが、グラフ機能は何か特定の用途でよほどグラフを書かせたいと言う目的がない限り、使う機会が無いなぁ、と感じています。学習用途なのでしょうが、私には縁がないし...文字列処理については、面白い使い勝手がありそうだと思っています。

ただ、文字列処理を除けば、Casio Basic を使う限りは、fx-5800P とそれほど大きな違いが無いように、最近思い始めています。
一応、Casio Basic コマンドリファレンスも、fx-9860GII 対応を始めていて、その作業中に上のようなことを思ったのです。fx-5800P を使い倒す意義を再発見したと言うことろでしょうか?


最後に、2つの話題を提供させて頂きます。

A: Facebook元役員「プログラミングを学ぶなら生涯仕事に困らないことを私が保証しよう。」
~これからの世の中ではプログラミングが必須のリテラシーだ、と言う論.

B: 60%の人はプログラミングの素質がない
~有名大学のコンピュータサイエンスを専攻してもプログラマとして使えない人が多いという経験の論証.


ちょっと考えさせられてしまいます。

A も B も極論に見えますが、あながち噓でもなさそう....う~む


Casio Basic 入門が、いきなり Getkey と Locate から始まっているのですが、それで良いのか?
むしろ、多くのブログやホームページで取り上げられているような、入力命令 ?" " と 出力命令 、そしてGoto を多用したプログラムこそが、誰でも電卓プログラミングが出来るようになるためのアプローチなのか?

...と、こんなことも考えてしまいます。


[2015/01/10 追記]
決めつけは良くない。あれから帰りの電車で半分眠りながら、ツラツラと考えたのですが、グラフ機能は結構遊べそうだと思い直しました。

ライフゲーム、フラクタル、カオスといった式だけでは分からない、やってみて分かる造形美と言うものがあります。俄然興味が沸いてきた次第。自分の浅はかさを恥じるばかりです。







応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ

keywords: fx-5800PCasioBasic換算プログラムプログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ
関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Basic入門35

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します

修正: 2015/01/26


 4. CasioBasicを使ってみる(続き)

Chapter 6

前回: Casio Basic入門34 を見る

◆ Chapter 6 の目標: プログラムを速くする
入力ボックスの改良と拡張

前回は、INP Ver 2.0  を作り、ストレスの無い実用的な応答性が得られました。そこで、今回はこれをさらに拡張して、負の整数/小数入力に対応した入力ボックスを作ります。プログラム名は IN です。


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-4
処理速度を意識して機能拡張する(2)

前回作った、INP Ver 2.0 は、0以上の小数入力まで拡張した入力ボックスです。

前回作成した INP Ver 2.0 (ファイル名: INP)

INP_Ver20_src_1 


このプログラムを拡張して、負の数値入力まで拡張した IN Ver 2.0 (プログラム名: IN)を作ります。


負数の扱い

fx-5800P には、負の数を入力するために、2つのキー [(-)][-] があり、高速化を考えた時、どちらかのキーのみを使わせることも考えられますが、プログラムの実用上、これらを限定するのは良くありません。そこで、先ずはこれら両方のキーを使えるようにプログラムを作り、満足ゆく応答性が得られない時は、どちらかに限定するようにしようと思います。

そこで先ず、負号 [(-)]  キーや減算記号 [-] キーを入力する時の処理を考えます。[(-)] のキーコードは 57、[-] のキーコードは 67 なので、Getkey コマンドの戻り値が 57 あるいは 67 の時、負号入力処理を行うようにします。

IN への拡張の元になる INP のプログラム構造を踏襲すると、IN のプログラム構造は以下のようになります。


 [初期化処理 1]

 [初期表示]

 Do


 [キーコード取得]

 [初期化処理 2]

 If (テンキーの場合):Then

  [テンキーの時の処理]

 Else If (小数点の場合):Then

  ※[小数点の時の処理]


 Else If (DELキーの場合):Then

  
[DELキーの時の処理]


 Else If (負記号の場合):Then

  [負記号の時の処理]

 IfEnd:IfEnd

 IfEnd:IfEnd

 LpWhile K≠47


 [後処理]

 Return


----------

赤文字で示したのは今回追加する処理です。さらに を付けたブロックは修正が必要と思われます。


負記号キーが押された時の処理

キーコード K が 57 あるいは 67 の時、負号キーが押された時の処理を行います。

Else If K=57 Or K=67
Then 
 [負記号キーが押された時の処理]
IfEnd


さて、現在入力している数が正の数か負の数かを管理するための変数が必要です。今回は新しい変数を使うのではなく、既に使っている変数を使い回すことにします(理由は後で述べます)。

元になる INP のプログラムを眺めると、7つの通常変数 CDFIXYZ はキー入力ループ内で使っていますが、変数 E はループ内で使われていないので、入力値の正負管理変数として E を使うことにします。

E は入力モード・インジケータの書式を指定するために、入力ボックスを呼び出す時に使われる変数で、キー入力ループの前の初期化表示処理と、ループの後の後処理で使われています。そこで、変数 E に格納されている変数を一旦別の変数に待避させておき、キー入力ループ内で E を自由に使います。そして、ループを出た時には、待避させていた本来の値を 変数 E へ戻し、後処理を実行させます。

E から待避させる変数には、今回は配列変数を用いることにします。87個の配列変数の多くは、プログラム内で使われていません。そこで、ループの前にある入力モード・インジケータの表示が終わった直後に、E を一旦 並列変数 Z[1] に待避しておきます(E→Z[1])。

これにより、キー入力ループ内では E を好きなように使えるようになり、ループが終わった直後に、Z[1] に待避させていた値を E に戻して(Z[1]→E)、後処理で入力モード・インジケータを消去します。

正数入力時に E = 1 とし、負数入力時に E = -1 とします。入力ボックス起動時の初期設定では、1→E、つまり正数入力としておきます。このように設定すれば、入力値の更新計算の時、変数 E を有効に使えそうです。

さて、負号は必ず最上位にしか入力できない、と言う大きな条件があります。つまり、C = 0 の時のみ負号の入力が許されます。これをプログラムコードで表現すると、以下のようになります。

If C=0:Then
Locate X,Y,"-"
-1→E:Isz C
IfEnd


負号を入力したら、E を -1 にします(-1→E)。そして入力桁数が1つ増えるので、Isz C とします。これが、負記号入力時の処理です。今回追加するのは、以下となります。

Else If K=57 Or K=67
Then
If C=0:Then
Locate X,Y,"-"
-1→E:Isz C
IfEnd:IfEnd


一番最後の IfEndElse If が追加されたので、合わせて追加しています。


テンキー入力時の処理

INP Ver 2.0 のテンキー入力時の処理を、抜き出してみます。

If (I≧1 And I≦9) Or K=25
Then
If C<D:Then
If F:Then
Z+I÷10^(F)→Z
Isz F
Else
10Z+I→Z
IfEnd
Locate X+C,Y,I
Isz C
IfEnd


これを変更して、負数の入力に対応させます。

テンキー入力時の処理を考えます。表示は単にテンキーの数字が入力されるだけなので、Locate コマンドを使った表示部分は、変更の必要がなさそうです。変更が必要なのは、上で赤文字で示した入力値 Z の更新の計算でしょう。

赤文字で示した小数入力の時の処理は、以下のようになっています;

Z+I÷10^(F)→Z

ここでは、Z + (I ÷ 10F) を計算して、Z に代入しています。この処理では、入力キーの数字 I に応じて、Z が更新されるのですが、I 自体は、常に一桁の正の整数です。一方、Z は、正になったり負になったりします。Z が正なら正数の入力ということですね。

この計算を数直線上でイメージすることで、Z + E(I÷10F) で良さそうだと、思いつきました。要するに、

Z + E(I÷10F) = Z + EI÷10F 

従って、

Z+EI÷10^(F)→Z

これをスグに思いつかなくても、以下のように考えるとうまくゆきます。


シミュレーション 1

-12.3 が入力されていて、さらに 4 をキー入力する時、その直前の状態は、以下のようになっています。

C=5   (5桁が入力されている)
I=4
F=2   (小数点を含めて、小数点以下2桁)
E=-1  (負数入力モード)
Z=-12.3
・ 表示: -12.3

この状態で、4 を入力すると、-12.34 となるべきで、Z を更新する計算は以下のようになるべきです;

つまり、
-12.34 = -12.3 - 0.04 = -12.3 - (4÷100)
= -12.3 - (4÷102) = -12.3 - 4÷102   [ 除算は減算より優先される ]
= -12.3 - 4÷10F       [ F=2 だから ]
= -12.3 + (-1)x4÷10F   
= Z + EI÷10F         [ Z=-12.3、E=-1、I=4 だから ] 
= Z+EI÷10^(F)


つまり、

Z+EI÷10^(F)→Z

とすれは、良さそうです。


シミュレーション 2

今度は、正数入力モードで、シミュレーションしてみます。

12.3 が入力されていて、さらに 4 をキー入力する時、その直前の状態は以下のようになっています;

C=4   (4桁が入力されている)
I=4
F=2   (小数点を含めて、小数点以下2桁)
E=1   (正数入力モード)
Z=12.3
・ 表示: 12.3

この状態で 4 を入力すると、12.34 となるべきです。

ここで、上で考えた処理

Z+EI÷10^(F)→Z

をそのまま適用してみます。

Z + EI÷10^(F) = Z + EI÷10F
= 12.3 + (1)x4÷102 = 12.3 + 0.04 = 12.34


正しく更新されることが分かります。

INP Ver 2.0 では、

Z+I÷10^(F)→Z

だったので、I E を乗算する(以下の赤文字を追加する)だけで、修正できることが分かります。

Z+EI÷10^(F)→Z


シミュレーション 3

次に、整数入力の時は、INP Ver 2.0 では以下の処理で 入力値 Z を更新しています。

10Z+I→Z

正負の整数入力に対応するには、上と同様に

10Z+EI→Z

で良さそうです。

そこで、-123 が入力されていて、4 をキー入力する時、その直前の状態は、

C=4   (4桁が入力されている)
I=4
F=0   (小数点を含めて、小数点以下0桁)
E=1   (数入力モード)
Z=-123
・ 表示: -123

なので、この状態から -1234 としたいわけです。

-1230 -

で良いので、

-123 x 10 - 4 = 10Z -I = 10Z +(-1)I = 10Z + EI

となり、これで良いことが分かります。

以上で、入力値 Z の更新計算をどうすれば良いか決まりました。

他の部分は、キー入力した数を Locate コマンドで追加表示するだけなので、INP Ver 2.0 と同じで良いわけです。
Locate X+C,Y,I
Isz C



INP Ver 2.0 のコードに、追加する部分を赤文字で示します。

If (I≧1 And I≦9) Or K=25
Then
If C<D:Then
If F:Then
Z+EI÷10^(F)→Z
Isz F
Else
10Z+EI→Z
IfEnd
Locate X+C,Y,I
Isz C
IfEnd


意外なことに、正負管理変数 E を2カ所に追加するだけでした。


小数点キーが押された時の処理

INP Ver 2.0 での処理は、以下のものです。

Else If K=26
Then
If F=0:Then
Locate X+C,Y,"."
Isz C:Isz F
IfEnd


入力値 Z の更新処理は行っておらず、単に小数点を表示するだけです。従って、入力値が正か負かは、この処理では無関係。
つまり、この部分は何も変更する必要はありません。


DELキーが押された時の処理

INP Ver 2.0 では、以下のようになっています。

Else If K=34
Then
If C:Then
If F:Then
F-1→F
F⇒Int(10^(F-1)Z)÷10^(F-1)→Z
Else
Int(Z÷10)→Z
IfEnd
C-1→C
Locate X+C,Y,">"
IfEnd


画面表示の変更は必要なさそうです。

赤文字で示した 入力値 Z の更新をどのように変更すれば良いか、考えてみます。

小数から末尾の数字を削除する時の Z の更新は、

F-1→F
F⇒Int(10^(F-1)Z)÷10^(F-1)→Z


となっています。Z が正の小数の時は、これで良いのですが、Z が負の小数の時は、どうなるでしょうか?
実は、そのまま適用でき、変更する必要は無さそうです。


シミュレーション 4

-1.2 と表示されていて、[DEL] キーで末尾を削除する直前は、以下の状態になっています。

C=4   (4桁が入力されている)
F=2   (小数点を含めて、小数点以下2桁)
E=-1   (負数入力モード)
Z=-1.2
・ 表示: -1.2

F-1→F
が実行されると、F=1 となります。そして、次の処理は、F が 0 でないので、条件ジャンプ命令 の右が実行され、

Int(10^(1-1)Z)÷10^(1-1)→Z 

ここで、

Int(10^(F-1)Z)÷10^(F-1) = Int(100Z)÷100 = Int(Z)÷1 = -1
 

なので、
-1→Z となって、Z=-1 となります。表示は、-1. と小数点が残っています。これで正常動作が確認されました。


シミュレーション 5

-1. と表示されている時、さらに [DEL] キーを押して、末尾の小数点の削除を行うことを考えます。その直前の状態は、以下になっています。

C=3   (3桁が入力されている)
F=1   (小数点を含めて、小数点以下1桁)
E=-1   (負数入力モード)
Z=-1
・ 表示: -1.

ここで、[DEL] キーを押すと、

F-1→F

が実行されて、F=0 となり、次の処理は、F=0 なので、⇒命令の次は飛ばされて実行されません。

F⇒Int(10^(F-1)Z)÷10^(F-1)→Z

つまり、Z は変更されず、Z=-1 のままです。表示は、-1 となり、正常動作が確認されました。
F=0 となったので、整数入力モードに切り替わります。


シミュレーション 6

-1 と表示されている時、さらに [DEL] キーを押して、末尾の 1 を削除する直前の状態は以下のようになっています。

C= 2   (3桁表示されている)
F=0    (小数点を含めて、小数点以下0桁)
E=-1   (負数入力モード)
Z=-1
・ 表示: -1

ここで、整数入力モードに切り替わっているので、つまり F=0 なので、Z の更新は、

Int(Z÷10)→Z

で行われます。Int(Z÷10) を計算すると、
Int(Z÷10) = Int(-1÷10) = Int(-0.1) = 0  
となるので、Z=0 となります。Int( ) 関数は、Int(-0.1) は、-0 ではなくて、0 となります。

表示は、- となって、負号が残った状態になります。これも正常動作です。この状態で、例えば 2 を入力すると、-2 になる(上のテンキー入力時の処理を参照)ので、まだ負数入力モードのままです。


シミュレーション 7

画面に負号 - のみが表示されている時、さらに [DEL] キーを押す直前の状態は、

C=1   (1桁が入力されている)
F=0   (小数点を含めて、小数点以下0桁)
E=-1   (負数入力モード)
Z=0
・ 表示: -

と、このようになっていて、ここで [DEL] キーを押すと、

Int(Z÷10)→Z

が実行され、Int(0÷10) = Int(0) = 0 なので、0→Z となり、Z=0 のままです。
表示は、何もなくなります。実際は、>>>>>>>> と入力ボックス起動直後の状態と同じになります。

このあと、テンキー 2 を入力することを考えてみます。すると、Z=2 となるはずですが、E=-1 のままなので、Z=-2 となってしまいます。というのも、テンキー入力時の処理で、Z の更新処理として、

10Z+EI→Z

が実行されるからです。これはマズイ、バグです。

シミュレーション 7 のように、負号を削除する時は、E の値を -1 から 1 に変更しておく必要があります。負号の削除は最上位桁の削除です。最上位が削除される時は、C=1 で、処理が終わるとき、C-1→C を実行して、C は 0 になります。そして、C=0 の時 E を 1 にすることで、正数入力モードに切り替えられます。

最上位桁を削除して、表示がなにも無くなるのは、入力ボックス起動時と同じ状態で、その時は負数入力モードではなくて、正数入力モードです。従って、最上位削除の時は、削除されるものが負号だろうと、数字だろうと、小数点だろうと、なんでも良いので、E を 1 にしてしまえば良いわけです。

そこで、

C=0⇒1→E

という処理を、DEL キーが押された時の処理の一番最後に追加しておきます。それ以外は、 INP Ver 2.0 と全く同じで変更は必要ありません。

DEL キーが押された時の処理は、以下になります。

Else If K=34
Then
If C:Then
If F:Then
F-1→F
F⇒Int(10^(F-1)Z)÷10~(F-1)→Z
Else
Int(Z÷10)→Z
IfEnd
C-1→C
C=0⇒1→E
Locate X+C,Y,">"
IfEnd


結局、今回追加したのは、上の赤文字の1行のみです。



これで、INP Ver 2.0 から IN Ver 2.0 への拡張ができました。負号管理は、 変数 E を使い回すようにし、負号キーが押された時の処理を追加し、それ以外はわずか3カ所の修正のみで拡張ができました。Ver 2.0 で採用した新しいロジックのおかげで、最小限の修正で済んだわけです。

正負小数入力に対応した入力ボックス IN Ver 2.0 が完成です。ファイル名を IN とします。

IN_Ver20_src 

INP Ver 2.0 から追加修正した部分を赤文字で示しています。


IN Ver 2.0 の仕様

fx-5800P を普通の関数電卓として使う時、0123 、.123 、 -.0123 と入力すると、そのまま表示されます。そして [EXE] キーを押せば、それぞれ 123 、0.123 、-0.0123 と表示されます。これは、fx-5800P の関数電卓としての入力仕様です。

IN Ver 2.0 でも同様で、例えば 0123.123-.0123 と入力すると、そのまま表示されます。そして [EXE] キーで確定すると Z には、それぞれ 1230.123-0.0123 と格納され、メインルーチンに戻ります。

さらに、Z の更新とリアルタイム表示を互いに独立させた結果、入力ボックスのプログラム上の桁数制限が無くなりました、fx-5800P で使う場合は、Locate コマンドの制限が1行あたり16桁なので、入力ボックスの桁数は最大16桁に制限されます。入力ボックスの表示開始桁に応じて桁数の最大値は表示行の右端までの桁数なので最大桁数は減ります。従って、最大16桁と言う言い方をします。fx-9860GII で使う場合は、Locate コマンドの制限が1行あたり21桁なので、入力ボックスの桁数は最大21桁に制限されます。こうして、柔軟性と移植性が得られました。

使用方法

メインルーチンから以下の書式で呼び出します。

△→X:△→Y:△→D:△→E
Prog "INPI"
Z→▽


は、任意の数、但し使用機種の画面範囲内に収まるように設定する。
  参考 fx-5800P: 1≦X≦16、1≦Y≦4、X+D≦16

- X: 入力ボックス表示開始桁
- Y: 入力ボックス表示開始行
- D: 入力ボックス桁数
- E: 入力ボックスインジケータの選択
   E=2: 画面右下に <EXE>:ENTER と表示
   E=1: 画面右下に ▶E と表示
   E=(上記以外): インジケータを表示しない
- Z: 入力ボックスで確定した数値が代入される

入力ボックス内部では、上記5つの変数以外に、C、I、F、配列変数を用いています。以上9個の変数は、入力ボックスを呼び出すたびに格納されている数値が変更されます。メインルーチンでこれら変数を使っても問題はありませんが、これら8個の変数は入力ボックスを呼び出すたびに変更されても良い変数として使ってください。特に配列変数は、入力ボックス内で87個の領域確保を行い、メインルーチンに戻る前に領域解放を行いますので、それを念頭に置いてメインルーチンで使用してください。


キー入力回数の測定

実際に前回と同じ方法で、INBOX TEST プログラムを使って、今回も入力応答性を実際に調べてみました。

比較対象は以下の2つのバージョン:

- INP Ver 2.0
前回作成したもの

- IN Ver 2.0
今回作成したもの

なお、整数入力と小数入力では、処理を分岐させているので、整数入力と小数入力の2通りで比較測定を行います。


整数入力時の応答性

評価プログラム INBOX TEST を以下のようにします。
ここで、INP Ver 2.0 のプログラム名を INP とし、IN Ver 2.0 のプログラム名を IN とし、入力ボックスの桁数を 10→D により10桁にします。

プログラム名: 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 "IN12":Z→S
Else If M=2
Then
3→X:2→Y:10→D:2→E
Prog "INP":Z→T
Else If M=3
Then
3→X:3→Y:10→D:2→E
Prog "IN":Z→U
IfEnd:IfEnd
IfEnd

Locate 1,4,"Z="

Locate 3,4,Z

Goto 0


比較は、メニュー2 INP Ver 2.0メニュー3 IN Ver 1.2 で行います。

測定方法は、前回と同じ方法です。
それそれの入力ボックスを開いた状態で、タイマースタートと同時にいずれかのテンキーを押しっぱなしにします。そして10桁目に表示された瞬間にタイマーを止め、時間を読み取ります。

表1 整数入力時の応答性比較
プログラムバージョン10桁入力所要時間1秒あたりの入力回数
IN Ver 1.2 整数入力3.6秒2.7回
INP Ver 2.0 整数入力1.6秒6.2回
IN Ver 2.0 整数入力1.6秒6.2回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

参考までに、以前 INPI Ver 1.2 と同じロジックで作った IN Ver 1.2 の測定結果も併せて掲載しました。このバージョンは入力にストレスを感じるほど応答性が悪く、正直言って公開できるレベルではありませんでした。

IN Ver 2.0 は、INP Ver 2.0 と差が認められず、同様の応答性能であることが分かりました。

実際にかなり速く入力してもキーの取りこぼしが無く、十分満足できる応答性になっていると思います。


小数入力時の応答性

INBOX TEST では、D→12 として入力ボックスの桁数を12桁に設定します。

INP Ver 2.0メニュー2)では、0. と2桁入力しておき、タイマースタートと同時に、いずれかのテンキーを押しっぱなしにし、12桁目(押しっぱなしで10桁目)が表示されたと同時にタイマーを止め、時間を読み取ります。

IN Ver 2.0メニュー3)では、-. と2桁入力しておき、タイマースタートと同時に、いずれかのテンキーを押しっぱなしにし、12桁目(押しっぱなしで10桁目)が表示されたと同時にタイマーを止め、時間を読み取ります。

そこで、INBOX TEST を以下のように、赤文字部分を変更します。

プログラム名: 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:12→D:2→E
Prog "INP":Z→T
Else If M=3
Then
3→X:3→Y:12→D:2→E
Prog "IN":Z→U
IfEnd:IfEnd
IfEnd

Locate 1,4,"Z="

Locate 3,4,Z

Goto 0



表2 小数入力時の応答性比較
プログラムバージョン10桁入力所要時間1秒あたりの入力回数
INP Ver 2.0 小数入力1.8秒5.5回
IN Ver 2.0 小数入力1.8秒5.5回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

IN Ver 2.0 の小数入力は、INP Ver 2.0 と差が見られず、同等の応答性能があることが分かりました。

実際に入力してみると、かなり速くキーを打っても、取りこぼしは発生せず、十分実用に耐えると思います。


Lbl/Goto ループと Do/LpWhile ループ

前回の INP Ver 2.0 と同様に、IN Ver 2.0 でのループの影響を調べて見ました。
キー入力中の処理は Do ~ LpWhile K≠47 ループ内に記述していますが、これを Lbl 0 ~ K≠47⇒Goto 0 ループに書き直して、応答速度の比較をしました。

表3 IN Ver 2.0 のループの違いによる応答性への影響比較
入力モードループ種別10桁入力所用時間1秒あたりの入力回数
整数入力
Lbl/Goto2.0秒4.7回
Do/LpWhile1.6秒6.2回
小数入力
Lbl/Goto2.3秒4.3回
Do/LpWhile1.8秒5.5回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

Lbl/Goto ループを使った時の応答性低下は、整数入力で25%、分数入力で 27% なので、Do ループを用いた高速化の効果が明かに現れています。INP Ver 2.0 では Lbl/Goto による応答性低下は 15~16% だったので、IN Ver 2.0 の方がより顕著です。制御構造がより複雑になると、Do ループに対して Lbl/Goto ループの処理速度の低下がより顕著になることが分かります。



まとめ

Chpater 6 では、以下の3種類の入力ボックスの高速化を図り、十分実用に使える Ver 2.0 ができました。

1. INPI Ver 2.0
0以上の整数入力のみに対応。0以上の整数のみの入力を行わせたいプログラムで使うことを想定していて、負数や小数入力のエラーチェックが不要になります。

2. INP Ver 2.0
0以上の整数/小数入力に対応。0以上の小数を含んだ数値みの入力を行わせたいプログラムで使うことを想定していて、負数入力のエラーチェックが不要になります。

3. IN Ver 2.0
正負小数/整数の入力に対応。最も汎用性のある入力ボックス。


プログラム高速化の指針

1) 比較演算、論理演算、配列変数の使用を極力控えること

2) 条件分岐には、以下を指針とする
 - If A≠0 よりも If A が高速
 - If A=B:Then [1つの処理]:IfEnd よりも A=B⇒[1つの処理] の方が高速

3) 制御構造 が複雑な(プログラムでは、Lbl/Goto ループでなくて、Do ループや While ループを使う

4) 上記3点を実現するための最適なロジックを考える

※ 制御構造とは、プログラムを構成する命令やコマンドを実行する順序のことです。プログラムは通常上から下へ実行され、If 文や⇒命令、Dsz/Isz命令 による条件分岐、Goto/Lbl などの無条件分岐や Do/While/For 文などのループ処理、そして Prog コマンド によるサブルーチン呼び出しがある時だけ、この原則を破ってすぐ下の処理ではなくて、別のところへジャンプします。分岐やループの処理の無いプログラムは最も単純な制御構造を持っています。分岐やループ、サブルーチン呼び出しが多くなるほど制御構造が複雑になります。


今回の高速化検討では、ロジックの見直しがうまく働いたと思います。結果的にストレスのない入力応答性が得られたので、当面これで良いことにします。さらに高速化可能なロジックがあれば、将来バージョンアップするかもをしれません。

今回は、プログラムライブラリに入力ボックス2.0 として公開します。



入力ボックス 2.0 が高速化したため、チョットした問題が出てきました。次回は、その対応について紹介します。



つづく...

Casio Basic入門36 / 目次




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



カシオプログラム関数電卓 FX-5800P-N カシオプログラム関数電卓 FX-5800P-N
(2006/09/22)
CASIO(カシオ)

商品詳細を見る



keywords: fx-5800PCasioBasic、入力ボックス, プログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

Casio Basic入門34

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します

最終更新:2015/01/25


 4. CasioBasicを使ってみる(続き)

Chapter 6

前回: Casio Basic入門33 を見る


◆ Chapter 6 の目標: プログラムを速くする
入力ボックスの改良と拡張

前回は、高速化したINPI Ver 2.0  を作りました。今回はこれを拡張して、0以上の小数に対応した入力ボックスを作ります。プログラム名は INP です。


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-3
処理速度を意識して機能拡張する

前回作成した INPI Ver 2.0 (ファイル名: INPI)

INPI_Ver20d_src_1 


このプログラムを基に、小数入力(但し0以上の正の小数)ができるように拡張します。


小数点の扱い

先ずは、小数点のキー [・] を入力するところから、全ては始まります。

[・] キーが押されたことを検出するには、Getkey コマンドの戻り値が 26 かどうかを判定します。

先ず、INPI のプログラム構造を確認しておきます。

 [初期化処理]

 [初期表示]

 Do


 [キーコード取得]

 If (テンキーの場合):Then

  [テンキーの時の処理]

 Else If (DELキーの場合):Then

  
[DELキーの時の処理]


 IfEnd:IfEnd


 LpWhile K≠47


 [後処理]

 Return


これを拡張して、キーコード 26 の [・] キーが押された時の処理を追加すると、次のプログラム構造になります。


 [初期化処理 1]

 [初期表示]

 Do


 [キーコード取得]

 [初期化処理 2]

 If (テンキーの場合):Then

  [テンキーの時の処理]

 Else If (小数点の場合):Then

  [小数点の時の処理]


 Else If (DELキーの場合):Then

  
[DELキーの時の処理]


 IfEnd:IfEnd

 IfEnd

 LpWhile K≠47


 [後処理]

 Return


----------

赤文字で示したのは、今回追加する処理です。さらに  を付けたブロックは修正が必要と思われます。


小数点キーが押された時の処理

小数点以下の桁数(小数点自身を含む)を新しい変数 F で管理することにします。例えば、現在入力されている数が整数の時は F=0、小数点のみが入力されている時は F=1、小数部が1桁の時は F=2、小数部が2桁の時は F=3、小数部が5桁の時は F=6 とします。F の初期値は、0 とします。従って、[初期化処理 2] で、

0→C:0→F

としておきます。[初期化処理 2] は、キー入力ループで必要な変数の初期化を行うブロックです(ブロックと言っても1行で書けますが...)。

小数点キーが押された時の処理は、以下のようになります。[・] キーのキーコードは 26 なので、

Else If K=26
Then
If F=0:Then
Locate X+C,Y,"."
Isz C:Isz F
IfEnd


ところで、Else If  で If が1つ増えたので、LpWhile K≠47 の前に忘れずに IfEnd を1つ追加しておく必要があります。
 ⇒ Casio Basicコマンドリファレンス - If ~ Then ~ IfEnd




上のコードを1行づつ追いかけてシミュレーションしてみます。今、12 が入力されている状態で、小数点キーを押すと、上のコードが実行されます。これが実行された後は、

C=3
F=1
・ 表示は、12.

となることが確認できます。

3桁入力されているので、C=3 は正しく、小数点を含めて小数点以下の桁数 F=1 となり、画面表示は 12 の後に小数点が付加されているので、このシミュレーション結果から、この部分が正しく動作することが分かりました。

さらに、小数 [・] を入力する場合を考えます。1つの数に小数点が2つ以上あってはいけないので、小数点は1回しか入力できないようにすべきです。上のプログラムコードでは、小数点を追加する処理は、If F=0:Then ~ IfEnd の中に書かれています。1度小数点を入力すると、 F は 1 以上になるので、If F=0:Then ~ IfEnd の中を実行することはありません。これで、小数点が2つ以上入力されることを防いでいます。




テンキーが押された時の処理

INPI のプログラムの中で、テンキーが押された時に実行される部分は、以下のようになっています。

If (I≧1 And I≦9) Or K=25
Then
If C<D:Then
10Z+I→Z
Locate X+C,Y,I
Isz C
IfEnd

・・・
IfEnd

これを小数入力時に対応できるように修正してゆきます。





12. が入力されている状態で、3 をキー入力する直前の状態は、

C=3   (3桁入力されている)
F=1   (小数点を含んで小数点以下1桁)
Z=12.
・ 表示: 12.

となっていますので、ここで 3 を入力すると I=3 となります。この状態で Z の値を正しく更新するには、

12 + 0.3

となれば良いので、これを実現するためには、

Z+I÷10→Z   ・・・ (1)

であれば良さそうです。

(注意)加算 (+) や減算 (-) よりも 乗算 (X) や 除算 (÷) が優先されるので、この式は、
Z+(I÷10)→Z
と同じです。少しでもプログラムを速く動かすために、余計な処理を省きます。

さらに、12.3 が入力されている状態で 4 をキー入力する直前の状態は、

C=4   (4桁入力されている)
F=2   (小数点を含んで小数点以下2桁)
Z=12.3
・ 表示: 12.3

となっています。ここで 4 を入力すると I=4 となります。このとき Z の値を正しく更新するには、

12.3 + 0.04 

となる計算が必要で、

Z+I÷100→Z   ・・・(2)

であれば、Z が 12.34 となります。ここで、上の (1)(2) に出てくる除数 10 や 100 は、実は 10F とすれば良いだろう、と言う予測をしています。ところで、小数の桁数が増えるので、どこかで Isz F を行って F を1つ増やす(インクリメント)しないといけないのですが、これを (1) や (2) の前か後か、どちらで実行すれば良いのかが、計算をシンプルにして処理を速くするためのポイントです。結果として、Isz F(1)(2) の後で実行すれば、10100 の代わりに 10F を使えるので、これが最適だと分かります。

もし、Isz F(1)(2) の前に実行すると、10F ではなくて 10(F-1) を使う必要があり、F-1 という余計な処理が出てくるので、処理速度向上には良くないわけです。

10F をプログラムで表現するには、10^(F) となります。
具体的には、[1] [0] [x] [ALPHA] [F] [ ) ] の順にキー入力します。

そこで、入力値 Z を更新する処理は、

Z+I÷10^(F)→Z
Isz F


とすれば良いことが分かります。

整数入力の場合は、

10Z+I→Z

となり、これは既に作っています。

処理速度向上を目的にしているので、分数入力時か整数入力時かに関わらず、1つの式で処理できれば理想的です。ところが、これら2つの式を見比べても、効率的に1つの式にまとめられそうにありません。



そこで、整数入力時か小数入力時かによって、これらのいずれかを実行させるような条件分岐処理を行うことにします。整数入力時か分数入力時かは、F の値を見れば分かります。F=0 の場合は整数入力時、F=0 で無い場合は小数入力時を意味します。実は、このようになるだろうと予測して、変数 F の初期値を 0 にしたわけです。

さらに言えば、F0 かそうでないかの条件分岐には、F⇒ と言う条件ジャンプ命令か、If F:Then という記法を使え、これらは共に処理速度が速いことが分かっているので、整数入力時に F=0 とし、小数の桁数に応じて F をインクリメントすると決めたわけです。その結果、F は「小数点を含めた小数点以下の桁数」という、普通の数学とはチョット異なる定義になっています。

表示については、INPI Ver 2.0 と同様に

Locate X+C,Y,I 

とすれば良く、整数入力時と小数入力時で共通して使えます。Z の更新と表示を独立させるという、ロジック変更の効果がここに現れています(実は、予めこれを狙ってロジックを変更したのですが...)。


では、テンキー入力時の処理を、具体的に作ります。そこで、INPI Ver 2.0 のテンキー入力時の処理を以下のように修正します。

INPI Ver 2.0 のテンキー入力時の処理
If (I≧1 And I≦9) Or K=25
Then
If C<D:Then
10Z+I→Z
Locate X+C,Y,I
Isz C
IfEnd


INP Ver 2.0 のテンキー入力時の処理
If (I≧1 And I≦9) Or K=25
Then
If C<D:Then
If F:Then
Z+I÷10^(F)→Z
Isz F
Else

10Z+I→Z
IfEnd
Locate X+C,Y,I
Isz C
IfEnd


追加部分を赤文字で示しました。

赤文字の一番上の行は、If F:Then となっています。これは、If F>0:Then と同じですが、処理速度は If F:Then の方が2倍速いことが分かっているので、(予定通りに(^^;)処理速度が速くなる記法を採用します。
 ⇒ Casio Basicコマンドリファレンス - If ~ Then ~ IfEnd 
 ⇒ fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較


DELキーが押された時の処理

INPI Ver 2.0 では、整数の最下位の数字を消せば良いので、10 で割ってから整数部を取り出すことで、Z の更新をしました。
例えば、1234 (=Z) と入力されている時、10 で割ると 123.4、 これの整数部を Int( ) 関数で取り出すので、

Int(Z÷10)→Z

としました。

小数入力時は、どうなるか?
例えば、今 12.34 (=Z) と入力されている時、最下位の 4 を消して、12.3 にしたいわけです。

Z (=12.34)10 倍して、123.4 とし、整数部を取り出して 123 にしてから、これを 10 で割ると 12.3 になります。具体的なコードで表すと、

Int(10Z)÷10→Z   ・・・(1)

となります。

12.34 と入力されていて、[DEL] キーを押す直前の状態は、

C=5   (5桁入力されている)
F=3   (小数点を含み、小数点以下3桁)
Z=12..34
・ 表示: 12.34

となっています。


シミュレーション 1

[DEL] キーで末尾を1桁減らすのですから、小数点以下の桁数も1つ減ります。そこで、先に F-1→F を実行してみます。
すると、F=2 となります。実は、(1) の2カ所に出てくる 10 は、上と同様に10F で処理できないかと予想しています。ところが、10F だと F=2 なので、100 になってしまい、ここは 10(F-1) (=10)でないとうまくゆきません。

F-1→F
Int(10^(F-1)Z)÷10^(F-1)→Z
Locate X+C,Y,">"
C-1→C


で良さそうで、確かに Z=12.3 となります。高速処理を目的にしているので、上と同様に (F-1) といった余計な計算をさせたくありません。ここで、10F を採用すると、上のテンキー入力所の処理では 10(F+1) が必要になり、両立が難しいことが分かります。どちらを取るか、の選択が必要です。

テンキーを入力時の高速化を優先させることにします。テンキー入力と [DEL] キーの頻度を考えると、テンキー入力が圧倒的に頻繁に実行される筈と考え、テンキー入力時の高速化を優先させる方が、入力時の体感も良くなると考えたわけです。


[DEL] キーによる削除処理での表示は、最下位の 4 は最上位から5桁目 (C=5) なので、4 が表示されているところに > を上書きします。

Locate X+C,Y,">"
C-1→C


で表示の更新を行ったのち、桁が1つ減るので C を1つ減らせば良いですね。


シミュレーション 2

続けて、[DEL] キーを押して、12.3 の末尾の 3 を消去するところをシミュレーションします。 
12.3 と表示されていて、[DEL] キーを押す直前には、

C=4   (4桁表示されている)
F=2   (小数点を含んで、小数点以下2桁)
Z=12.3
・ 表示: 12.3

となっています。

ここで、[DEL] キーを押した時の処理は、上と同様に、

F-1→F
Int(10^(F-1)Z)÷10^(F-1)→Z
Locate X+C,Y,">"
C-1→C


ここで、

Int(10^(F-1)Z)÷10^(F-1) = Int(1xZ)÷1 = 12 

となります。

なお、今 F=1 なので、10^(F-1) = 10(F-1) = 100 = 1 となります。何をゼロ乗しても、その結果は 1 と定義されているので、10のゼロ乗も 1 になり、これで正しいことがわかります。

さて、表示については、最上位から4桁目 (C=4) の 3 の上に > を上書きし、桁が1減るので、C-1→C としておきます。

これで、入力値 Z の更新と表示が正しく動作することがわかりました。


シミュレーション 3

続いてさらに [DEL] キーを押して、小数点を削除する際、その直前の状態は、

C=3   (小数点を含んで3桁表示されている)
F=1   (小数点を含んで、小数点以下1桁)
Z=12
・ 表示: 12.

となっています。

先ず、F-1→F が実行され、F=0 となります。小数点がなくなれば、F=0 になるのは正しい動作です。

続いて以下が実行されます。

Int(10^(F-1)Z)÷10^(F-1)→Z

F=0 なので、この計算は以下のようになります。

Int(10^(F-1)Z)÷10^(F-1) = Int(10F-1 x Z) ÷ 10F-1
= Int(10-1 X Z) ÷ 10-1 = Int(0.1 x Z) ÷ 0.1 = Int(1.2) ÷ 0.1
= 1 ÷ 0.1 = 10 
[Z=12 を代入]

となり、本来 Z = 12 となるべきところ、Z=10 となるので、これはマズイ!

今は、小数点を削除するだけで、Z の値は変化させる必要がありません。そこで、F=0 の時には、この計算を行わないようにすれば、良いので、この Z の更新処理を、

F⇒Int(10^(F-1)Z)÷10^(F-1)→Z

と変更すると、うまくゆきます。F=0 でない時はこの計算を実行し、F=0 の時は実行しません。これも、F をうまく定義したことの効用です。

F⇒ 命令の処理時間は 4.1ミリ秒、If A の処理時間は 6.2 道秒なので、F⇒ が 1.5 倍速いことが分かっているので、 命令を使っています。
 ⇒ fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較 の 表参照

なお、F が負の数になると、上の F⇒ を使った Z の更新がおかしくなる心配があります。例えば、F = -1 の時は、上の Z の更新計算を実行することになり、計算結果がおかしくなりそうです。F を1つ減らす処理は、[DEL] キーが押された時の削除処理でしか行いません。そこで、F0 になれば、さらに1つ減らす処理を行わないようにすれば良いので、F の値の管理をきちんと行うことにします。





シミュレーション 4

さらに続いて [DEL] キーを押した時をシミュレーションします。
[DEL] キーをオス直前の状態は、以下のようになります。

C=2   (2桁表示されている)
F=0   (小数はなく、整数になっている)
Z=12
・ 表示: 12

この状態で、[DEL] キーで削除を行うと整数を削除することになるので、INPI Ver 2.0 で作った処理をそのまま適用すれば、問題ありません。小数からの削除を行うのか整数からの削除を行うのかは、F の値で条件分岐します(テンキー入力時の処理と同様です)。条件分岐した整数の末尾を1つ減らす処理で、F-1→F が含まないようにします。こうすれば、F0 より小さくなることはありません。

以上から、小数からの末尾削除については、以下のコードで良いことをシミュレーションから確認できました。

F-1→F
F⇒Int(10^(F-1)Z)÷10^(F-1)→Z
Locate X+C,Y,">"
C-1→C



整数からの削除と小数からの削除

さて、整数から最下位(末尾)の桁の削除する時と、小数からの最下位(末尾)の桁を削除する時では、Z の更新のために用いる計算が以下のように異なります。

整数からの末尾削除時は、

Int(Z÷10)→Z

小数からの末尾削除時は、

F⇒Int(10^(F-1)Z)÷10^(F-1)→Z

これらを、1つの式(処理)にまとめるのは難しそうなので、整数からの削除と、小数からの削除は、処理を分岐させることにします。

今入力されている数が整数か小数かは、F の値で判別できます。F=0 の時は整数、F>0 の時は小数なので、これを処理分岐の条件に使うことにします。


DEL キーを押した時の処理全体

さて整数のみを扱う入力ボックス INPI Ver 2.0 では、  [DEL] キーを押した時の処理は、以下です。

Else If K=34
Then
If C:Then
Int(Z÷10)→Z
C-1→C
Locate X+C,Y,">"
IfEnd


これに赤文字部分を追加して、小数対応すると、以下のようになります。

Else If K=34
Then
If C:Then
If F:Then
F-1→F
F⇒Int(10^(F-1)Z)÷10^(F-1)→Z
Else
Int(Z÷10)→Z
IfEnd
C-1→C
Locate X+C,Y,">"
IfEnd


Cつ減らす処理と、Locate コマンドによる削除の結果の表示処理は、修正なしにそのまま使えます。ロジック変更の狙い通りです。

なお上と同様に、If F>0:Then の代わりに、速度が2倍近い表記 If F:Then を使っています。 
 ⇒ fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較 の表参照



上記以外の処理は、INPI Ver 2.0 と全く同じで問題ありません。今回作った0以上の小数入力に対応した入力ボックスを INP Ver 2.0 とし、プログラム名を INP とします。

INP_Ver20_src_1 



INP Ver 2.0 の仕様

高速化のため、Z の更新とリアルタイム表示を完全に独立させるようにロジックを変更した結果、INP Ver 2.0 は、入力仕様が Ver 1.2 と異なっています。

Ver 1.2 では、最上位に 0 や 小数点の入力をさせないようにするために余計は処理を加えていました。Ver 2.0 ではこの処理を省いています。

fx-5800P を普通の関数電卓として使う時、0123 や .123 と入力すると、そのまま表示されます。そして [EXE] キーを押せば 123 や 0.123 と表示されます。これは、fx-5800P の関数電卓としての仕様です。

INP Ver 2.0 でも同様で、例えば 0000123 や .0000123 と入力すると、そのまま表示されます。そして [EXE] キーで確定すると Z123 や 0.0000123 と格納され、メインルーチンに戻ります。

さらに、Z の更新とリアルタイム表示を独立させた結果、入力ボックスの桁数制限がプログラム上不要になりました。しかし、ハードウェアに依存して Locate コマンドによる制限は残ります。fx-5800P で使う場合は、Locate コマンドの制限が1行あたり16桁なので、入力ボックスの桁数は最大16桁に制限されます。実際の入力ボックスの桁数は、表示開始位置から右端までの桁数となりますので、最大16桁と言う言い方になります。fx-9860GII に移植して使う場合は、Locate コマンドの制限が1行あたり21桁なので、入力ボックスの桁数は最大21桁に制限されます。こうして、INP Ver 2.0 は、ソフトウェアとしての柔軟性と他機種への移植性が得られました。


使用方法

メインルーチンから以下の書式で呼び出します。

△→X:△→Y:△→D:△→E
Prog "INPI"
Z→▽


は、任意の数、但し使用機種の画面範囲内に収まるように設定する。
  参考 fx-5800P: 1≦X≦16、1≦Y≦4、X+D≦16


- X: 入力ボックス表示開始桁
- Y: 入力ボックス表示開始行
- D: 入力ボックス桁数
- E: 入力ボックスインジケータの選択
   E=2: 画面右下に <EXE>:ENTER と表示
   E=1: 画面右下に ▶E と表示
   E=(上記以外): インジケータを表示しない
- Z: 入力ボックスで確定した数値が代入される

入力ボックス内部では、上記5つの変数以外に、C、I、F、配列変数を用いています。以上9個の変数は、入力ボックスを呼び出すたびに代入されている数値が変更されます。メインルーチンでこれら変数を使っても問題はありませんが、これら9個の変数は入力ボックスを呼び出すたびに変更されても良い変数として使ってください。特に配列変数は、入力ボックス内で87個の領域確保を行い、メインルーチンに戻る前に領域解放を行いますので、それを念頭に置いてメインルーチンで使用してください。

なお、INPI に比べて、INP では、使う変数が1つ増えています(変数 F が追加)。


キー入力回数の測定

実際に前回と同じ方法で、INBOX TEST プログラムを使って、今回も入力応答性を実際に調べてみました。

比較対象は以下の2つのバージョン:

- INP Ver 1.2
INPI Ver 1.2 のロジックのまま拡張したもの。ソースコードは割愛します。

- INP Ver 2.0
今回作成した 新しいロジックの INPI Ver 2.0 を拡張したもの

なお、整数入力と小数入力では、処理を分岐させているので、整数入力と小数入力の2通りで比較測定を行います。


整数入力時の応答性

評価プログラム INBOX TEST を以下のようにします。
ここで、INP Ver 1.2 のプログラム名は INP12Ver 2.0 のプログラム名を INP とし、入力ボックスの桁数を 10→D により10桁にします。

プログラム名: 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 "INP12":Z→T
Else If M=3
Then
3→X:3→Y:10→D:2→E
Prog "INP":Z→U
IfEnd:IfEnd
IfEnd

Locate 1,4,"Z="

Locate 3,4,Z

Goto 0


比較は、メニュー2INP Ver 1.2メニュー3INP Ver 2.0で行います。

測定方法は、前回と同じ方法です。
それそれの入力ボックスを開いた状態で、タイマースタートと同時にいずれかのテンキーを押しっぱなしにします。そして10桁目に表示された瞬間にタイマーを止め、時間を読み取ります。

表1 整数入力時の応答速度比較
プログラムバージョン10桁入力所要時間1秒あたりの入力回数
INPI Ver 1.2 整数入力2.2秒4.5回
INPI Ver 2.0 整数入力1.4秒7.1回
INP Ver 1.2 整数入力2.6秒3.8回
INP Ver 2.0 整数入力1.6秒6.2回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

参考までに、INPI Ver 1.2Ver 2.0 の結果も併記しました。

表1から、以下が分かります。
INP Ver 2.0 は、Ver 1.21.6 倍の入力応答性になる。
INP Ver 2.0 は、INPI Ver 2.0 に比べて、87% 程度の入力応答性になる。

実際に色々な数を入力してみると、かなり速く入力してもキーの取りこぼしが無く、十分満足できる応答性になっていると思います。


小数入力時の応答性

INBOX TEST では、D→11 として入力ボックスの桁数を11桁に設定します。そして、入力ボックスを開き、先に小数点を入力しておきます。すると残り10桁なので、タイマースタートと同時に、いずれかのテンキーを押しっぱなしにし、10桁目が表示された瞬間にタイマーを止め、時間を読み取ります。

なお、INP Ver1.2 は桁数制限があるので10桁までしか入力できません。一方で、新しいロジック(仕様)の Ver 2.0 は1行に収まる限り桁数の制限はありません。Ver 1.2十分遅いことが明かなので、INP Ver 2.0 のみを測定することにします。

そこで、INBOX TEST を以下のように、赤文字部分を変更します。そして、メニュー2 を測定に使用します。

プログラム名: 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:11→D:2→E
Prog "INP":Z→T
Else If M=3
Then
3→X:3→Y:10→D:2→E
Prog "INP":Z→U
IfEnd:IfEnd
IfEnd

Locate 1,4,"Z="

Locate 3,4,Z

Goto 0



表2 小数入力時の応答速度比較
プログラムバージョン10桁入力所要時間1秒あたりの入力回数
INP Ver 2.0 整数入力1.6秒6.2回
INP Ver 2.0 小数入力1.8秒5.5回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

参考までに、INP Ver 2.0 の整数入力の結果を併記します。

表2から、以下が分かります。
INP Ver 2.0 の小数入力時の応答性は、整数入力時の88%程度。

実際に色々な数を入力してみると、かなり速くキーを打っても、取りこぼしは発生せず、ストレスのない実用に十分耐える応答性が得られたと思います。


Lbl/Goto ループと Do/LpWhile ループ

INPI Ver 1.2 では、入力ボックスで入力が確定されるまでのループに Lbl/Goto ループを使っていました。一方、INPI Ver 2.0 を作る時は、Do/LpWhile ループに変更しました。プログラムが長く、複雑になると Lbl/Goto ループの処理時間が長くなることが経験的に分かっているので、このような変更を行いました。但し、INPI Ver 2.0 では、このループの変更により応答性の顕著な変化は見られません。

INP Ver 2.0 では、INPI Ver 2.0 に比べてプログラムの処理がより長く、制御構造がより複雑になったので、試しに Do/LpWhileLbl/Goto に換えて、応答性の比較測定を行ってみました。

表3 INP Ver 2.0 の Lbl/Goto と Do/LpWhile の応答性への影響比較
入力モードループ種別10桁入力所用時間1秒あたりの入力回数
整数入力
Lbl/Goto1.9秒5.2回
Do/LpWhile1.6秒6.2回
小数入力
Lbl/Goto2.1秒4.7回
Do/LpWhile1.8秒5.5回
※ この測定は、非常に個人差があるので、比較の意味しかありません。

表3から、INP Ver 2.0 では、Lbl/Goto ループによる応答性低下は、整数入力で 15%、小数入力で 16% になり、Do ループを用いた高速化の効果が明らかに現れました。

Goto 命令は ジャンプ先の Lbl を検索する際に、プログラムの一番最初から順に検索を行うことは、簡単な実験から分かっています。Goto 処理では Casio Basic 特有の特別な処理が行われていることが分かってて、制御構造が複雑になると処理速度が低下します。今回はその効果が明らかに現れています。

ある程度長くて制御構造が複雑なプログラムでは、高速化を考える際には、Lbl/Goto ループを使わず、Do ループや While ループを使うべきです。 Goto の特殊な処理の詳細は、"楽屋裏 - Dsz によるループ脱出" に書いたので、ご興味があればご覧ください。




プログラム高速化の指針

これまでのところ、Casio Basic プログラムを高速化するには、少なくとも以下の指針が有効だと言えます。

1) 比較演算、論理演算、配列変数へのアクセスを極力減らすこと

2) プログラムロジックの見直しによる、余計な処理の排除

3) ループには、Lbl/Goto ループを使わず、Do ループや While ループを用いること



今回作った INP Ver 2.0 を基に、次回から正負の小数入力ができるように拡張してゆきます。



つづく...

Casio Basic入門35 / 目次




応援クリックをお願いします。励みになるので...

人気ブログランキングへ


FC2ブログランキングへ



カシオプログラム関数電卓 FX-5800P-N カシオプログラム関数電卓 FX-5800P-N
(2006/09/22)
CASIO(カシオ)

商品詳細を見る



keywords: fx-5800PCasioBasic、入力ボックス, プログラミング入門プログラム関数電卓

リンク集 | ブログ内マップ



関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

2015 謹賀新年

皆様、あけましておめでとうございます。

数えてみると、昨年は103本の記事を書いていました。今年も引き続き fx-5800P や fx-9860GII の Casio Basic に焦点を絞った話題を紹介することになりそうです。今年もよろしくお願い致します。

私自身が、fx-5800P や Casio Basic を触っていて、見つけたこと、工夫してみたこと、試してみたことを、比較的リアルタイムに発信してきました。但し、タイプミス、変な日本語、勘違い、バグなどを修正することも多く、お見苦しくて申し訳ありません。

読者の方々からのご指摘にも感謝しております。読者の方々からのコメントは、とてもありがたいものです。頂いたご意見が、新しいエントリーになることもありました。コメント欄で話が尽きないこともありました。

今年も応援頂けますよう、お願い申し上げます。


2015年元旦






関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

最新記事
最新コメント
カテゴリ
C# (3)
検索フォーム
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

実際に触って気づいたこと、自作プログラム、電卓プログラミングについて書いています

おもしろい・役に立つならクリックしてください。励みになります。
にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村


人気ブログランキングへ


FC2ブログランキングへ


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

RSSリンクの表示
最新トラックバック
ブロとも申請フォーム

この人とブロともになる

QRコード
QR