Casio Basic入門33

Casio Basic入門
<目次>

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

最終更新:2015/01/25

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

Chapter 6

前回: Casio Basic入門32 を見る


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

前回は、INPI Ver 1.2 へのバージョンアップを行いました。今回は、さらに高速化して Ver 2.0 を作ります。


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-2
ロジックの見直しでプログラムを高速化する


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

INPI_Ver12_src_1 

ループ全体の論理演算と比較演算の個数と所要時間

Ver 1.0 (INPI10)
Ver 1.2 (INPI12)
処理種別 (時間)個数時間 (ミリ秒)個数時間 (ミリ秒)
倫理演算 (10ミリ秒)770330
比較演算 (11.5ミリ秒)141619103.5
合  計
231
133.5
※ 処理時間(ミリ秒)の絶対値は、必ずしも正しくなく、比較のための目安として使っています。


今回は、1つめの If (I≧1 And I≦9) Or K=25 の場合の処理に含まれる以下のコードに着目し、

C≠1 Or A≠25⇒Isz C
C=1⇒K→A


これらの処理を見直して、さらに高速化を試みます。

結論から言えば、これらの処理をほとんど削除できました。先ずは、今回作った Ver 2.0 のコードを Ver 1.2 と並べてみます。変更する部分は赤文字で示しています。

INPI_Ver12_src_2 INPI_Ver20d_src_1 

Ver 1.2Ver 2.0 のループ全体の論理演算と比較演算の数をまとめてみます。

ループ全体の論理演算と比較演算の個数と所要時間

Ver 1.2 (INPI12)
Ver 2.0 (INPI20)
処理種別 (時間)個数時間 (ミリ秒)個数時間 (ミリ秒)
論理演算 (10ミリ秒)330220
比較演算 (11.5ミリ秒)10115780.5
合  計
145
100.5
※ 処理時間(ミリ秒)の絶対値は、必ずしも正しくなく、比較のための目安として使っています。

単なる目安としても、論理演算と比較演算の回数を減らすことで、応答性の大幅な向上(約50%向上)が期待できるわけです。


キー入力回数の測定

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

INPI バージョン10桁入力所要時間1秒あたりの入力回数
1.02.8秒3.5回
1.22.2秒4.5回
2.01.4秒7.1回

この測定は、非常に個人差があるので、比較の意味しかありませんが、Ver 1.2 に対してVer 2.0 の応答性は、実際に約50% 向上したと言えます。最初の Ver 1.0 に対しては2倍の入力応答性が得られました。

実際に使ってみると、かなり高速化されたと感じると思います。



今回の Ver 2.0 では、論理演算を比較演算を減らすために、プログラムの仕様を変更しています。それによって、今回着目している上記2行の部分から、論理演算と比較演算を完全に取り去り、Isz C のみにできました。


Ver 1.x のロジック

入力ボックスでは、主に2つのことを行います。

1) 入力操作に応じて、内容を表示する
2) 入力操作に応じて、結果を変数に保存する

Ver 1.0 では、計算して更新した値を変数Z に代入し、そのZ Locate コマンドで表示しています。入力結果と表示が常に同じであることが保証されるので、この方法を採用しました。

キー入力するたびに、何桁目を入力しているかをプログラムで管理しています。変数C がこれから入力する桁数を示し、C=0 は何も入力されていない状態、C=1 は1桁、C=2 は2桁入力されている状態を示します。

INPI は、10桁以上入力できない仕様にしていました。Z が11桁以上になると、fx-5800Pの仕様のため、Z を表示する際に 指数表示になり、桁数の管理ができなくなることが、その理由です。そこで、桁数の最大を 10 としていました。入力ボックスの表示桁数は変数D で管理しているので、D10 を超えると D=10 とするようにしています。

キー入力を進めてゆき、現在の桁数CD を超える場合は、それ以上入力できないように管理しています。[DEL] キーで消去する場合も、現在の桁数C を減らしてゆき、C=0 となれば、それ以上削除できないようにしています。

このように、変数C を用いた桁数の管理は、正常動作に必要です。


さて、例えば 001234 と6桁入力した場合、Z の値は1234 となり、桁数が2つ異なってしまい、桁数管理がうまくゆかなくなります。そこで、最初の桁(=一番左の桁)には、0 を入力できないようにしています。そのための処理が、今回着目した部分(下記)です。

C≠1 Or A≠25⇒Isz C
C=1⇒K→A


INPI を正負小数入力に拡張すると、小数点やマイナス記号も、最初の桁(=一番左の桁)に入力させないように抑制しなければならなくなり、小数点の位置や負号の有無の管理と併せて、この入力抑制処理がさらに膨らんで複雑になることが容易に想像され、実際に作ってみると、かなり複雑になってしまいます。

要するに、入力結果の数Z をそのまま表示させる方法を諦めて、他の方法に変更しなければ、処理をシンプルにして、論理演算や比較演算を減らすことができないと考えました。


Ver 2.0 のロジック

そこで、入力操作に応じた「表示」 と 「変数への保存」を独立させることにしました。

その結果、001234 と入力すれば、表示は 001234 となり、現在の桁数を管理する変数C には 6 が格納されます。そして、変数Z には 1234 と保存されます。変数Z を表示することを止めて、入力キーコードから変換したキーの数字をキー入力のたびに表示するようにました。

これにより、桁数管理の整合性をとるための、上記の2行の処理は不要になります。それに伴って、変数A を使うことがなくなり、変数 A を使うために、プログラムの最初で A→Z[1] とし、最後で Z[1]→A とする処理も不要になりました。 

さらに、このロジックでは、Locate コマンドを使った表示処理で、指数表示の影響を考える必要がなくなり、最大桁数の管理も不要になりました。必要なら fx-5800P の最大桁数16桁を入力ボックスの桁数にすることも可能になります。但し、INPI を呼び出す時に、プログラムによっては、最大桁数の管理を行う必要が出てきます。これは作るプログラム次第で考えれば良いので、入力ボックスのプログラムで考える必要はありません。

最初から、これを思いつけば苦労は無かったのですが、しかたありません。むしろ、不適切なロジックに皆さんを付き合わせてしまって、大変申し訳なく思っています。ハードウェア性能をうまく引き出せば、凝ったプログラムも可能になります。今回は、悪いお手本とそれを改善するところをご覧頂きたいと思います。



INPI Ver 2.0 プログラムの説明

個々の処理について、説明を加えました。赤文字で書いている処理については個別に説明します。

EngOff           [初期設定]:通常の整数表示のために EngモードをOff
0→Z
             [初期設定]:入力結果を代入する変数を 0 で初期化
87→DimZ
         [初期設定]:全てのキーコードを代入する領域確保
1→Z[35]:2→Z[36]
  [初期設定]:テンキーの数字とキーコードの関連付け
2→Z[37]:4→Z[21]
  [初期設定]:テンキーの数字とキーコードの関連付け
5→Z[22]:6→Z[23]
  [初期設定]:テンキーの数字とキーコードの関連づけ
7→Z[31]:8→Z[32]
  [初期設定]:テンキーの数字とキーコードの関連づけ
9→Z[33]
          [初期設定]:テンキーの数字とキーコードの関連づけ

If E=2:Then
              [初期表示]:入力モードインジケータ E=2の時
Locate 6,4,"<EXE>:ENTER"
  [初期表示]:このように表示
Else If E=1
               [初期表示]:入力モードインジケータ E=1の時
Then
Locate 15,4,"▶t"
           [初期表示]:▶ を表示させたいので先ずは▶t
Locate 16,4,"E"
            [初期表示]:これで ▶E と表示
IfEnd:IfEnd

For 1→I To D
      [初期表示]:指定桁数D だけ繰り返す
Locate X+I-1,Y,">"
 [初期表示]:指定座標(X, Y) から D桁だけ > を表示
Next
0→C
            [初期設定]:現在の入力桁を管理する変数C を 0 で初期化

Do
              [ループ]: LpWhile K≠47 との間のループ

Do
              [キーコード取得]:何かキーが押されるまでループが回る
Getkey→K
         [キーコード取得]:キ-コードを変数K に代入
LpWhile K=0
       [キーコード取得]:何もキーが押されない時ループ継続
Z[K]→I
           [キーコード取得]:キーコードを変数 I に代入, 1-~9以外は 0

If (I≧1 And I≦9) Or K=25
  [テンキーが押下時:数字を一桁ずつ得てZ再計算]
Then
If C<D:Then
     ⇒現在の入力桁 C が最大桁数 D 以上では何も処理しない
10Z+I→Z
       ⇒入力数を更新して変数Z に代入
Locate X+C,Y,I
   ⇒指定座標(X, Y) のXからC桁目に I を表示
Isz C
           ⇒桁数管理変数C を1つ増やす。C+1→C よりも Isz C が高速
IfEnd

Else If K=34
     [DELキーが押下時:数字を右から一桁ずつ削除してZ再計算]

Then
If C:Then        ⇒桁数管理変数C が 0 の時は何もしない ⇒ 削除しない
Int(Z÷10)→Z     ⇒Z を 10 で割った結果の整数部を得て、Z に代入
C-1→C          ⇒桁数が1つ減るので、現在の桁 C を1つ減らす、Dsz C 不可
Locate X+C,Y,">"  ⇒削除した数字の跡に > を表示
IfEnd
IffEnd:IfEnd

LpWhile K≠47
       [ループ] EXEキーが押されない限り Lbl 0 へ戻る


For 1→I To D-C      [後処理]:入力桁を示す >>>> を消去
Locate X+C+I-1,Y," "  [後処理]:入力数の1つ右から最大桁数までスペース表示
Next

If E=2:Then         [後処理]:入力モードインジケータ E=2の時
Locate 6,4,"      "   [後処理]:インジケータをスペース11個で上書き
Else If E=1          [後処理]:入力モードインジケータ E=1の時
Then
Locate 15,4," "      [後処理]:インジケータをスペース2個で上書き
IfEnd:IfEnd

0→DimZ           [後処理]:配列変数の領域を解放
Return
             [メインルーチンへ戻る]



INPI Ver 2.0 の使い方

メインルーチンにおいて、INPI を呼び出す直前に、必要な変数設定を行います。
- X: 入力ボックス表示開始のX座標 
- Y: 入力ボックス表示開始のY座標
- D: 入力ボックスの桁数 (最大入力桁数)
- E: 入力モードインジケータの設定
   ・E=2:  画面右下に <EXE>:ENTER と表示
   ・E=1: 画面右下に ▶E と表示
   ・E=0 あるいはそれ以外: インジケータの表示なし

[EXE] キーで入力確定すると、入力値が変数 Z に格納されて INPI が終了するので、メインルーチンでは INPI 呼び出し直後に Z を適切な変数に代入しておく。

例)
3→X:2→Y:6→D:1→E
Prog "INPI20"
Z→A


INPI では、上記の変数以外に、変数 CIK を使います。これら3つの変数に加えて上記の5つの変数は、INPI で使用され値が変わります。メインルーチンでは、これら5つの変数を使えますが、INPI を呼び出すたびに変更されても良い変数として使ってください。


INPI Ver 2.0 の入力桁数制限について

入力ボックスの桁数の制限は、Locate コマンドの制限に依存します。つまり、画面の桁数が16桁なので、最大16桁まで使えます。
但し、入力した数値をプログラムで計算に使う場合は、fx-5800P の計算精度に留意する必要があります。

1回の計算につき10桁目の誤差が±1となります。計算結果が10桁以上になると(Norm 2 指定の場合)指数形式になり、その場合は仮数部の最下位桁の精度が±1になります。一回の計算では、10桁未満であれば計算精度が保証されるわけですが、計算を繰り返す際に上記の桁数制限を受ける場合は、そこで誤差が発生します。

但し10桁の制限は、実はPCで使える開発環境でも、多くの場合同様ですから、fx-5800P に限った問題ではありません。この点は意外に認識されないことが多いのですが、その意味で fx-5800P は十分な精度を持っていると言えます。

なお、INPI では、プログラム内で敢えて桁数制限を設けないことにします。そもそも INPI を使って10桁の計算をすることは殆ど無いと思いますし、柔軟な仕様にしておく方が何かと良いと思うからです。

(注) INPI Ver 1.0 および Ver 1.2 では変数 Z をそのまま 表示させる仕様であったので、桁数制限が10桁でした。従って、入力桁数が10桁以上にならないように、プログラム内で制限をかけていました。Ver 2.0 では、この点がより柔軟になっています。


INPI Ver 2.0 での入力値 Z の更新方法と表示方法について

上のプログラムで、赤文字で示した部分が、本プログラムの一番重要なところなので、説明します。

Ver 2.0 では、キー操作ごとに入力値 Z を更新計算します。リアルタイム表示は変数 I を使い、Z を用いません。
これらの動作は、現在の入力位置 C と 最大桁数 D を用いて制御しています。

テンキー入力時の 入力値 Z の更新

[2] [0] [1] [4] と順次入力する場合をみてみます。

[2] キーを押すと、Z=2 となります。次に [0] で Z=20 とし、さらに [1] で Z=201[4] で Z=2014 としたいわけです。Z を10倍し、テンキーの番号 (変数 I )を加えれば、Z を更新できることが分かります。つまり、

10Z+I→Z

Z の更新計算となります。


DEL キー入力時の入力値 Z の更新

Z2014 の時、[DEL] キーを押ると、最下位の 4 を削除する仕様です。つまり、Z=201 としたいわけです。2014 から 201 にするには、201410 で割って、整数部を取り出せば良いので、

Int(Z÷10)→Z

が、Z の更新計算となります。


テンキー入力時の表示の変更

入力ボックスの表示開始座標は(X, Y)で、指定桁数(最大桁数)は、D です。そして、現在の入力桁を、C としています。テンキーの番号は変数 I です。

最初に [2] を押すと、最上位(一番左の桁)に 2 を表示する仕様です。入力した直後は、C=0 です。

入力ボックス1桁目表示直後 (C=0)
 X X+1X+2X+3X+4X+5
2>>>>>





Locate X, Y, I とすれば良いですね。そして、現在の入力桁 C はつ増やして(インクリメントして)、1 になります。

続いて  [0] を押すと、左から2桁目に 0 を表示したいので、表示桁は1つ右にズレます。表示行はそのまま同じです。

Locate X+C,Y,I

とれば、良さそうですね。

入力ボックス2桁目表示直後 (C=1)
 X X+1X+2X+3X+4X+5
20>>>>





表示後、C をインクリメントします。C+1→C とすれば良いのですが、Isz C とする方法もあります。前回紹介した各処理の時間比較の結果、Isz CC+1→C よりもかなり速いことが分かっているので、高速化が目的の INPI Ver 2.0 では、Isz C を採用します。

さらに、[1] キーを押すとき、

Locate X+C,Y,I
Isz C


で、うまくゆくことが分かります。

入力ボックス3桁目表示直後 (C=2)
 X X+1X+2X+3X+4X+5
201>>>





続けて、[4] キーを押すと、

Locate X+C,Y,I
Isz C


で、問題無いことが分かります。

入力ボックス4桁目表示直後 (C=3)
 X X+1X+2X+3X+4X+5
2014>>




そして、Isz C を実行して C4 となります。


DEL キー入力時の表示の変更

2014 と入力されている状態で、[DEL] キーを押すと、末尾の 4 を消去する仕様です。末尾の 4 を消去するには、4 > を上書きします。

2014 と入力されている状態では、C=4 となっています。そこで、先ず最初に C を1つ減らし(ディクリメントし) C=3 とした後

Locate X+C,Y,">"

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

入力ボックス表示 (C=3)
 X X+1X+2X+3X+4X+5
201>>>





さて、C のディクリメントの方法は、C-1→C とするか、Dsz C とする方法があります。高速化のためには、Dsz C が良いのですが、これだと問題があります。

Dsz C は、ディクリメント後 C0 になると、次の処理を飛ばして、2つめの処理までジャンプする命令です。入力ボックスを完全に消去する時、C=1 となっているので、この状態でディクリメントすると C=0 となります。すると Dsz C により次の処理を飛び越えてしまうので問題です。従って、ここでは C-1→C を採用します。

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



ループの見直し

Ver 1.2 では Lbl 0 ~ Goto 0 をループに使っていました。プログラムの制御構造 が複雑になると、Lbl / Goto をループに使うよりも Do / LpWhileWhile / WhileEnd ループを使う方がプログラムが速くなることが経験的に分かっています。プログラムが長くなるほど、その効果は大きくなります。実のところ、今回の INPI Ver 2.0 では、Lbl 0 ~ Goto 0Do ~ LpWhile K≠47 に変更しても、実際の測定では明かな差は出ていません。しかし、これより複雑な制御構造を持つプログラムでは、その差が出てくる可能性があるので(実際に差がでてきます)、今回は Do / LpWhile ループに変更しておきます。

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



INPI Ver 2.0 の仕様

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

Ver 1.2 では、最上位に 0 の入力をさせないようにしていましたが、このために余計な処理を加えていました。Ver 2.0 ではこの処理を取り去っています。

fx-5800P を普通の関数電卓として使う時、0123 と入力すると、そのまま表示されます。そして [EXE] キーを押せば 123 と表示されます。fx-5800P の仕様と同じで問題ない筈です。

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

さらに、Z の更新とリアルタイム表示を独立させた結果、入力ボックスのプログラム上の桁数制限が無くなりました、fx-5800P で使う場合は、Locate コマンドの制限が1行あたり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
      fx-9869GII: 1≦X≦21、1≦Y≦7、X+D≦21

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

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



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




つづく...

Casio Basic入門34 / 目次




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

人気ブログランキングへ


FC2ブログランキングへ



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

商品詳細を見る



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

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



関連記事

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

Casio Basic入門32

Casio Basic入門
<目次>

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

最終: 2015/01/25

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

前回: Casio Basic入門31 (Chapter 5)を見る


お詫び

※ 本Chapter 6 は、Chapter 3 の続編で、Chapter 3 で作ったプログラムを高速化するのが 本Chapter 6 の目的です。なお、Chapter 3 自由自在に入力する Caso Basic入門17Casio Basic入門18 を修正・追記しています。 特に Casio Basic入門18 は誤記や説明不足が多くあり、多くの部分を修正・追記しています。申し訳ありません。必要に応じて、もう一度ご覧ください。



Chapter 6

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

はじめに


Chapter 3 - 自由自在に入力する - で作った入力ボックス サブルーチン INPI Ver 1.0 は、0以上の正の整数の入力のみに対応しています。これを正負小数入力に対応するために、必要な処理を追加して拡張したものを作って、使っていましたが、入力応答がとても遅くて、入力時にストレスを感じているので、公開には至っていません。個人的に我慢して使っていると言う状況でした。

最初から、高速応答するように作っていれば良かったのですが、私自身も Casio Basic を手探りで調べながら、分かったことを公開しているので、拡張してみてから応答が非常に遅くて実用に耐えられないので、これをなんとか改善したいと思っていました。

そこで、遅いプログラムの高速化の具体例として、入力ボックスを高速応答させるための改良方法を紹介します。そして今回作る拡張版入力ボックスを活用して頂きたいと思い、プログラムライブラリ にも収録しました。

但し、Chapter 3 はそのまま残します。私の失敗を公開することで、これをお読みの方が同じ失敗に陥らなければ幸いです。


実際に行ったこと

さて、最終的に正負小数に対応した入力ボックス IN を高速化して、ストレスの無い入力ができるようになりました。さらに高速化したことで、機能拡張もてきました。この時の考え方や手法を、今回 Chapter 6 で紹介します。

実際に私が手元で行った改良と機能拡張の流れと、作った機能拡張版 (INPINは以下の通り;

入力ボックス機 能
INPI0との正の整数の入力に対応
INP0 と正の整数と正の小数の入力に対応
IN0 と正負整数と正負小数の入力に対応

1) INPI Ver 1.0 を拡張し、0と正の小数に対応した INP Ver 1.0 および 正負小数に対応した IN Ver 1.0 を作成

2) INPI を高速化して Ver 1.2 とした 
INPI Ver 1.2 をプログラムライブラリで公開。そこそこ許容範囲と判断したものの、まだ物足りない。

3) 同じ手法を INPIN に適用して、Ver 1.2 とした
INP Ver 1.2IN Ver 1.2 はまだ遅いので、非公開のまま。

4) INPI Ver 1.2 をさらに見直して Ver 2.0 とした
※ 入力応答を速くするために、ロジック(プログラム仕様)を少し変更。
INPI Ver 2.0 の高速化は十分に満足できる応答性になった。

5) 同じ手法を INPIN に適用して、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 専用にした 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.02.8秒3.5回
INPI Ver 1.22.2秒4.5回
INPI Ver 2.01.4秒7.1回
INP Ver 2.01.8秒 / 1.6秒※1)5.5回 / 6.2回※1)
IN Ver 2.01.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.0Ver 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 の方が、A-1→A よりも Dsz A の方が2倍程度速い。


次に、変数アクセス、比較・論理演算、条件分岐の処理速度比較を、以下で行いました。
 ⇒ 変数アクセス、比較・論理演算、条件分岐の速度比較

その結果は、

制御変数 (インデックス) を使った配列へのアクセス(読み出しと書き込み処理)
これらには、配列変数、行列、リストが使える。
これらの読み出しや書き出しは非常に遅いが、使う場合はこれらの中で相対的に速いのが「配列変数」。そこで配列には「配列変数」を使うべき。但し、そもそも配列変数へのアクセスは遅いので、読み出しや書き込みの回数を極力少なくするべき。

比較演算や論理演算
これらは、算術演算(+、-、×、÷)よりも遙かに遅い。さらに変数同士の比較演算や論理演算処理の方が、変数と数値(即値)との処理よりも少し速い。従って、即値(数値)はできるだけ使わず、さらに比較演算や論理演算を使う回数を減らすべき。

条件分岐
条件判定に使う比較演算や論理演算が、条件分岐処理の殆どの時間を占める。さらに条件判定には、変数同士を用いる方が、変数と即値(数値)を用いるよりも少し速い。

この結果を一覧にしたのが以下の表です。

表 fx-5800P Casio Basic 処理時間の比較
処理内容処理時間 (ミリ秒)
A⇒4.1
通常変数アクセス5.4
If A6.2
If A Else7.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
累乗 (A)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)

INPI_Ver10_sec_1 

キー入力の応答性を速くするのが目的なので、高速化対策が必要なのは、青文字で示した Lbl 0K≠47⇒Goto 0 で挟まれるループの内の処理です。入力ボックスが >>>> で表示された後、入力が完了して [EXE] キーを押すまで、このループが回ります。

ここで真っ先にに気がつくのは、赤文字で示した If 文、つまりテンキー入力部での条件判定部分です。この条件判定では、論理演算 (AndOr) が合計5個、そして比較演算子 (=) が合計7個使われています。このループ内全体では、論理演算が7回、比較演算が14回、配列変数 Z[ ] が使われています。

上記の、各コマンド・命令の処理時間の調査から、論理演算に約10ミリ秒、比較演算に約11.5ミリ秒かかることが分かっています。

遅 い 処 理赤文字のIf文ループ全体
種別時間 (ミリ秒)個数時間 (ミリ秒)個数時間 (ミリ秒)
論理演算10660
770
比較演算11.5780.514161
合  計
140.5
231
※ 時間(ミリ秒)の絶対値は、必ずしも正しくなく、比較の為の目安として使っています。

こうしてみると、この If 文の条件判定だけでも 140.5 ミリ秒ループ全体の処理時間 231 ミリ秒のかなりの割合を占めていることが分かります。

この最初の INPI のファイル名を INPI10 としてください。次に倫理演算と比較演算を減らしたプログラムを作り、Ver 1.2 とし、プログラム名を INPI12 としてください。


INPI Ver 1.2 (プログラム名: INPI12)

Ver 1.0 に対して、変更した部分を赤文字で示します。

INPI_Ver12_src_1 

INPI Ver 1.2 のコードから、Lbl 0 ~ K≠47⇒Goto 0 のループ内にある、論理演算と比較演算の個数を調べて、Ver 1.0 と比較してまとめてみます。

ループ全体の論理演算と比較演算の個数と所要時間

Ver 1.0 (INPI10)
Ver 1.2 (INPI12)
処理種別 (時間)個数時間 (ミリ秒)個数時間 (ミリ秒)
論理演算 (10ミリ秒)770330
比較演算 (11.5ミリ秒)141619103.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 を起動すると、シンプルな画面を表示

IN TEST 1 

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

IN TEST 2 

上記の評価プログラム INBOX TEST では、[1] キーを押せば INPI Ver 1.0 が呼び出され、[2] キーを押せば INPI Ver 1.2 が呼び出されます。実際に入力して、Ver 1.0Ver 1.2 を比較してみてください。応答性が改善されていることは体感できると思います。


実際に測定を試みる

タイマーソフトを使って、10 桁入力する時間を測定します。INPI は、Ver 1.0Ver 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.02.8秒3.5回
1.22.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 文の最初で変数 I1→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.0Ver 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)、K41 が代入され、次に 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 / 目次




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

人気ブログランキングへ


FC2ブログランキングへ



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

商品詳細を見る



keywords: fx-5800PCasioBasic、世界時間換算, プログラミング入門プログラム関数電卓

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




続きを読む

関連記事

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

番外編 - プリンタ複合機

番外編 - プリンタ複合機
e-Gadget

2014年12月21日
2014年12月22日 追記
2015年08月07日 追記

[2015/08/07]: 結局こうなった...を一番下に追記しておきます。


10年以上使っていた HPのプリンタ複合機 Photosmart 3210a がついに壊れた(/_;)
肝心の印刷がうまくできなくなって、半年。プリンタがなくても困らないことに気がつき、これはちょっとした発見でした。しかしながら、年賀状印刷のシーズンを迎え、そのままというわけにも行かず、ついに買い換えました。

我が家のプリンタ複合機の事情は、当ブログ e-Gadget に大きな影響があります。e-Gadget で掲載するプログラム電卓の画面のスキャンが、買い換えにより出来なくなります。これはイタイ(/_;)

このHPの複合機を購入するとき、スキャナ機能にこだわりました。まさか電卓の液晶表示をスキャンするとは、購入当時は考えませんでしたが、本のスキャンの品質にこだわりました。当時の市場では、スキャナには2種類あり、センサがCCDのものとCMOSのもの(CIS)がありました。CCDタイプは高価になるものの、段差があっても綺麗にピントがあってスキャンできるので、私はCCDタイプにこだわったのです。その結果、電卓の画面のスキャンは問題無く綺麗にできました。

ところが、最近は普及価格のモデルでは、CMOS Image Sensor (CIS) タイプしか選択肢がありません。そこで、量販店で様々な複合機で、電卓画面のスキャンを試しました。電卓のスキャンを徹底的に試す私は、担当者には奇異に映ったことだと思いますが、私には切実な問題なわけです。

結果は、当然ながらまともにスキャンできるものは皆無でした。

そうなれば、あとはインクコストと、修理にならないための堅牢な作り、つまりはトータルの経済性を追求するのみ。結局、インク等の運用コストが安そうで、作りがしっかりしていそうな、Canon PIXUS MG7530 (A4複合機の最新モデル) に、落ち着きました。Canon機の樹脂の厚みが特段厚いわけでもないのですが、構造や機構がよく考えられていて、部材の脱着や差し込みなどが、余計な力を加えずスムーズにできるようになっているのは、さすがです。

購入後、ダメ元で 電卓画面のスキャンを試しましたが、液晶表示はガラス面から距離があるため、やはりピントが合わず...

残念!

それにしても、CANON機に標準添付されているスキャンソフトは、かなり酷いですね。HP機のスキャンユーティリティの完成度の足下にも及びません。

ばかでかい HP 機を、スキャナのためだけに置いておきたいのですが、それも難く、泣く泣く捨てるしかなさそうです。そして、今後の e-Gadget に影響が出そうです。デジカメを使った撮影環境を整える必要がありそうです。

CISスキャナでも、電卓の液晶をきれいにスキャンできる方法について、ご提案があれば是非ともお聞かせください。
或いは、スマホやデジカメを使って、映り込みや光源反射の無い綺麗な撮影を手軽にできる方法があれば、是非ともご教示ください。


[2014年12月22日 追記]
CCDセンサを搭載した小型のフラットベットスキャナを調べてみたところ、EPSON の GT-S640 が実売で¥7,500程度であることを発見。安いといっても、この価格。最後の手段としてとっておくことにして、お金のかからない良い方法を継続して探索することにします。


[2015年8月7日 追記]
やはりCCDセンサを使ったスキャナ機能は捨てるには勿体ないので、なんとか場所を確保してスキャナ機として使っています。プログラム電卓の液晶表示を綺麗にスキャンできるのは、e-Gadget 運用には不可欠です。



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

人気ブログランキングへ


FC2ブログランキングへ


keywords: プリンタ複合機e-Gadget

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

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

年末恒例、電卓すす払い

2014年12月20日

年末も押し迫ってきました。この時期は年賀状の準備に併せて、所有電卓のすす払いを行っています。


恒例の電卓すす払い

日常使い以外の電卓は、動態保存を目指しています。乾燥剤入りの箱から出してきて、清掃、動作確認、必要に応じて電池交換を行います。

My Calcs 

これらは、実際に新品として購入して、一度は日常使いをしたものばかりです。右下に写っている fx-995ES だけが例外で、カシオのスタンダード関数電卓の第三世代の最終型としての記念に購入したものです。2015年2月には 高精細液晶を搭載した fx-JP900 が発売予定で、これは第四世代のスタンダード関数電卓と言えます。
・第一世代: 最初の関数電卓
・第二世代: 数式通り入力タイプ
・第三世代: 数学自然表示タイプ
・第四世代: 高精細液晶タイプ
        ⇒ Casio fx-JP900


過去の名機レビュー

プログラム電卓は、今も昔も高価な製品なので、調べて納得してから購入すると言うのが通常です。2回だけ衝動買いをし、結果的に、最初は大ハズレ(fx-4500P)、2回目は大当たり(fx-5800P)でした。

今回は、ちょっと懐かしさもあって、記事にしてみようと思います。

FX-502P
FX-502P & Manual

これは、FX-502P 、一世を風靡した手帳サイズのプログラム関数電卓です。保証書には 1979年4月とあります。35年経った今でもきちんと動作します。生まれて初めて個人で所有した電卓が、いきなりこの機種でした。親に買って貰ったもので、当時は搭載されている関数全部が理解できませんでした(/_;)
昨年まであったプログラムライブラリがなぜだか見つからず、年末の大掃除での捜索対象です。人生で初めて作ったプログラム(反射ゲーム)はこの電卓で作ったものです。

 ⇒ FX-502P / 602P / 603P のプログラム

アセンブラのような言語で、最初は分かりにくいものでしたが、最近の Casio Basic には無い、間接ジャンプ、間接参照ジャンプといったまさにアセンブラのような命令があって、限られたプログラム領域やメモリで効率良く動作させる仕様です。まさに神のようなプログラムが多く発表されたものです。

FX-602P
FX-602P & Manuals 

FX-502P ではプログラムが保存しきれなくなったのでFX-602P を入手し、日常使いしていました。1984年6月19日の日付の保証書も残っていて、30年経った今でもきちんと動作します。プログラム言語は FX-502P とほぼ互換です。今でも FX-602P Page と言うサイトが残っていて、当時の "神プログラム" に熱狂した雰囲気を味わうことができます。

FX-502P や FX-602P は30年以上経てもなお健在、その品質の高さには驚きます。

FX-603P
FX-603P & Manuals 

FX-502P の系統の互換機種の最終バージョンである FX-603Pで、これもきちんと動作します。これは21世紀に入ってもまだ販売されていた超ロングセラーの製品です。私自身、2007年まで使っていたので、そんなに古いと言う感覚がないのですが、残っている保証書には 1992年4月 とあるので、22年も前に購入したことになります。液晶がドットマトリックスになり、2行表示となり、さらにアルファベットの表示ができるようになったのでプログラムの幅が広がりました。当時は2行表示でも凄い便利だと思ったものです。

カシオのプログラム関数電卓第一世代の最終形と言うべき記念のモデルです。

実は、その後カシオのプログラム関数電卓搭載のプログラミング言語は、迷走の時代を迎えます。

fx-4500P
fx-4500P 
迷走の時代の代表選手 fx-4500P です。fx-4500PA は多く売られたのですが、末尾が PA でなくて P のモノはそれほど多く市場に出回らなかったようで、ある意味希少価値があるようです。海外のコレクタが 比較的高値で購入したがっているようです。fx-4500PA はボタン電池を3個使うのですが、fx-4500P はボタン電池2個使いなので、省電力で経済的なのかも知れません。

残っている保証書には、1990年2月27日とあるので、24年選手です。

私の fx-4500P は残念なことに 電池を入れ替えても LOW BATTERY と表示され、液晶が濃く表示できない状態です。計算はできるので、かろうじて動態保存しています。普通に考えれば24年で故障するのは不思議でもなんでも無いのですが、他が凄すぎです。

このモデルの特長として、1つのキーに割り当てられる機能が多すぎで、操作性が悪い点がありました。それだけなら慣れれば済むのですが、プログラミング言語が、中途半端でとても使いにくいのは致命的でした。

右下に [EXE] キーがあるのが、この機種の特長の1つです。当時のカシオは FX-603P 系統の [=] を持つシリーズと、[EXE] を持つシリーズの2つが存在しており、言語仕様が互いに大きく異なっていました。

結果的には、[EXE] キーの系統が、現在のプログラム関数電卓やグラフ関数電卓に繋がっているわけですが、FX-603P でできたことが、どうやっもできないと言うことが多く、せっかく期待して購入したのですが、結局 FX-603P の購入に至ります。

従って、、それほど使っていないのですが、所有品の中でこれだけが電源回りに故障が発生していることから、品質面も試行錯誤していたのかも知れません。私が購入した電卓の中で、唯一のハズレ品でした。


fx-911s / fx-991S / fx-991W / fx-991MS / fx-991ES / fx-993ES
仕事の環境が大きく変わったため、技術計算やプログラムを利用することが激減し、スタンダード関数電卓を愛用していた時期があります。上の写真には写っていない、fx-911s が初めて買った スタンダード関数電卓でした。FX-603P と同様の手帳タイプで、満員電車の押しくらまんじゅうで壊れてしまい、fx-991S を購入。これも同じく手帳タイプで同様に満員電車で壊れました。

次に買ったのが、写真に写っている fx-991W で、ハードケースに変わったおかげで、満員電車で生き残ることができました。fx-991W を最も長く愛用しました。その後、fx-991MS 以降でガッカリしたのは、3桁区切りの記号が表示されなくなったことです。さらに fx-991ES以降では、3桁区切り記号が無いだけでなく、視認性の劣る青液晶になってしまいました。安い青液晶に切り替えたのは、バブル崩壊とデフレ突入による不景気の象徴だと思っています。

幸いなことに2015年2月発売予定の fx-JP900 は、黒液晶に戻り、3桁区切りが復活します。さらに高精細液晶の搭載です。カシオの本気度がうかがえます。


fx-5800P
fx-5800P-3
fx-5800P を店頭で見て、その場で衝動購入したのですが、購入当時はスタンダード関数電卓の高級機と言う感覚で使っていました。プログラムは作らず、使いもしませんでした。

ふと、プログラムを作ってみようと思って触ると、FX-603P とは別世界、スラスラとプログラムが書けて、Casio Basic の使いやすさに驚きました。そして、触っているうちに Casio Basic の能力の高さに惚れ込みました。但し、fx-5800P の取扱説明書は、FX-603P の時代と異なって、プログラミングについては、ほとんどヤッツケ仕事としか思えないお粗末な記述しかありません。カシオは、分かる人だけ使えば良いと本気で思っているのでしょうか? 優れた Casio Basic なのにもったいない話です。

近年の Casio Basic は構造化プログラミング言語なので、実用的で使いやすいプログラムをかけます。その魅力にハマッて色々と調べた結果をまとめておきたい、知らない人に知って欲しいと言う趣旨で e-Gadget  を始め、究極のワンテーマブログが続いています。


fx-9860GII
今年は年末になって、fx-9860GII を入手しました。fx-5800P よりも処理能力は圧倒的に高いのですが、使い勝手の面でみると fx-5800P の方が圧倒的に良いと感じています。従って、今でも日常使いは fx-5800P のままです。チョットした憧れのあった fx-9860GII ですが、どちらか1つを選べ、と今言われると fx-5800P を選ぶと思います。今のところ...

ところで、 fx-5800P 用の Casio Basic のプログラムをいくつか fx-9860GII に移植してみています。

 ⇒ fx-5800P プログラムライブラリ - キーコード取得
 ⇒ fx-9860GII への移植 - ピタゴラス数
 ⇒ fx-9860GII への移植 - 素因数分解

ここで、分かったことは、ほんのチョットしたことだけ気をつければ移植性が極めて高いと言うことです。処理能力の低い fx-5800P でまともに動くように作れば、fx-9860GII では問題なく動作します。搭載されている Casio Basic は、fx-5800P よりも fx-9860GII がバージョンが上のようで、fx-5800P に無いコマンドが多くあるので、fx-5800P でどうしてもできないことが、fx-9860GII で実現します。理屈の上では...です。

実際に、fx-9860GII の特長を活かし、fx-9860GII で是非とも使いたいプログラムが、いつか出来ると思います。fx-5800P になく、fx-9860GII にある面白い点の1つに、C言語で書いたプログラムを走らせられることがあり、ホビー機としては楽しませてくれそうです。Windowsプログラミングが染みこんでしまった体には、以前の MS-DOS で C のプログラムを作っていた頃を思い出させてくれて、懐かしい感じがします。


Basic は時代遅れなのか?

ネットを見ていますと、Basic 言語は教育用の初心者向きで、実用向きではないと言う言説を未だに見聞きしますが、PC用のプログラムでも Visual Basic で書かれたものが立派に業務用として使われています。C言語系(敢えて、C++、C# や Javaなどを含めますが...)が優れていると一言でいえるものでは無いと思うのです。適材適所で 複数の言語を使い分けるのが最良でしょう。プログラミングは宗教ではなく、実用ツールなのですから...

Basicでプログラムを書くのは確かに楽です。電卓プログラミングで言えば、FX-603P 系のアセンプラのような言語に比べると、Casio Basic は圧倒的に実用的です。プログラムの種類や目的によっては、Casio Basic ではできないことがあり、その時は Casio Basic 以外を使いたいと思います。その意味でfx-9860GII により、プログラム電卓活用の幅が広がるのではないかと、楽しみです。


そして、Casio Basic の勧めCasio Basic入門 に繋がります。


長々とここまでお付き合い頂き、ありがとうございます。





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

人気ブログランキングへ





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

商品詳細を見る



keywords: fx-5800P、fx-9860GIICasioBasicプログラム関数電卓

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


関連記事

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

Casio Basic入門31

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
最終更新: 2015/01/24

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

Chapter 5

◆ Chapter 5 の目標: サブルーチンを使いこなす

前回: Casio Basic入門30 を見る


前回までに、キー長押しによりタイムゾーンの変更・設定機能を呼び出すようにしました。


夏時間の開始と終了の日時は、毎年異なります。そこで2015年の夏時間の開始・終了日時を表示する機能を追加し、さらにチョットした仕上げを行ってプログラムを完成させます。

最終的に完成させるプログラムを一番下に掲載しているので、先にそれを見て分かれば、先へ進むのも良いでしょう。



Chapter5-9
キー長押しによる別機能の呼び出し

27-TZInfo  

このように、ヨーロッパとアメリカ(北米)について、それぞれの夏時間の開始と終了日時を表示する機能を追加します。

なお、この表示は 2014 年のヨーロッパやアメリカの夏時間の期間を示しますが、もう 2015年がやってきます。
そこで、2015年の夏時間の期間を表示するようにします。

2015年の夏時間の期間
・ヨーロッパ: 2015年3月29日 午前2時開始、2015年10月25日 午前3時終了
・アメリカ  : 2015年3月9日 午前2時開始、2015年11月1日 午前2時終了
※ 夏時間終了の時間がヨーロッパとアメリカで1時間違う)

実際問題、現地の人は深夜は寝ているので、アメリカでは 10月25日の朝以降は夏時間ではありません。ヨーロッパでも同様に 11月1日の朝は夏時間ではありません。そこで、本プログラムでは、朝の時点で夏時間かどうかの基準で表示(下記)を行うことにします。

  DLS IN 2015
EUR: 3-20⇒10-24
USA: 2-9 ⇒10-31


2016年には、ここの表示を更新する必要があります。

さて、この表示を呼び出すためにはメイン画面で [3][4] キーを長押しすることにします。そして、その表示は 画面表示ルーチン TZS で行うことにします。



以上が今回の機能追加の内容で、具体的には以下のように進めます。

1.初期化処理
特に変更なし。

2.メニュー番号取得処理
今回は、[3] キー と [4] キーの長押しを検出し、検出されたときに、メニュー変数 M5 を入れる。

3.入力処理
M=5 の時は、単に情報を表示するだけで、キー入力処理は行なわない。

4.時間の計算
M=5 の時は、情報を表示するだけなので、何も計算することはない。

5.時間表示の更新
一旦画面全体を消去し、夏時間の情報を表示したのち、メイン画面を再表示する。再表示は 画面表示サブルーチン TZM を用いる。TZM の変更はない。

6.ループ構造
既にある While 1 ~ WhileEnd ループの中に、上記追加コードを入れる。


メインルーチンの擬似的なプログラムは、以下になります。追加・修正するところが分かると思います。


[初期化処理]

Prog "TZM"  [メイン画面表示]

While 1

  [メニュー番号取得処理]

  
[ [3]  および [4] キー長押しを検出し 両方ともメニュー番号 M=5 とする処理]

  If M=0:Then
    [日本時間入力処理] (時間から「時」と「分」の分離も行う)
  Else If M=1:Then
    [ドイツ時間入力処理] (時間から「時」と「分」の分離も行う)
  Else If M=2:Then
    [LA時間入力処理] (時間から「時と「分」の分離も行う)
  Else If M=3:Then
    キー入力処理は行わない。時間から「時」と「分」の分離のみ行う
  Else If M=4:Then
    キー入力処理は行わない。時間から「時」と「分」の分離のみ行う
  IfEnd:IfEnd
  IfEnd:IfEnd
  IfEnd

  If M=0:Then
    [時間計算]
  Else If M=1:Then
    [時差計算]
  Else If M=2:Then
    [時間計算]
  Else If M=3:Then
    [時間計算]
  Else If M=4:Then
    [時間計算]
  
Else If M=5:Then
    Prog "TZS"  
[夏時間情報の表示]
    Cls
    Prog "TZM"  
[メイン画面表示]

  Else If M=6:Then
    Prog "TZS"  
[ヨーロッパタイムゾーン設定]
    [時間計算]
    Prog "TZM"  
[メイン画面表示]
  
Else If M=7:Then
    Prog "TZS"  
[アメリカタイムゾーン設定]
    [時間計算]
    Prog "TZM"  
[メイン画面表示]

  IfEnd:
IfEnd
  IfEnd:IfEnd
  IfEnd:IfEnd
  IfEnd
:IfEnd

  
Prog "TZD"    [時間の再表示]

WhileEnd


(赤文字は機能追加部分)



1.初期化処理
変更なし。



2.メニュー番号取得処理 - キー長押し処理


[3] キー と [4] キーの長押しを検出して、メニュー変数 M5 を入れます。

長押し検出は、既に説明したものを適用するだけです。

メニュー番号取得処理のソースコード
-1→M
Do
Getkey→K
LpWhile K=0
K=25⇒0→M
K=35⇒1→M
K=36⇒2→M
K=37⇒3→M
K=21⇒4→M

0→C
While Getkey=37
Isz C:C=9⇒Break
WhileEnd:C=9⇒5→M
0→C
While Getkey=21
Isz C:C=9⇒Break
WhileEnd:C=9⇒5→M

0→C
While Getkey=35
Isz C
C=9⇒Break
WhileEnd
C=9⇒6→M
0→C
While Getkey=36
Isz C
C=9⇒Break
WhileEnd
C=9⇒7→M


(赤文字は追加部分)



3.入力処理

入力処理を行わないので、[入力処理ブロック] は何も変更しません。



4.時間計算

時間計算は行いませんが、ここで表示サブルーチン TZS を呼び出し、TZS で夏時間情報を表示させます。TZS 変更については、以下で説明します。

次に、TZS での表示が終わり、メインルーチンに戻ってきたら、一旦画面表示全体を消去 (Cls コマンドを使用)し、メイン画面表示サブルーチン TZM を呼び出して、選んだタイムゾーンに合わて画面を再表示します。TZM の変更は不要です。


メインルーチンに追加するプログラムを示します。今回変更するメインルーチン全体は、一番下に掲載しています。

メインルーチンに追加するプログラム
Else If M=5
Then Prog "TZS"
Cls:Prog "TZM"
IfEnd


タイムゾーン設定サブルーチン TZS を呼び出します。TZS の変更点は、以下で説明します。
  Prog "TZS"

TZS から戻ってきた時、夏時間情報が表示されたままです。そこで、Cls コマンドで画面を消去します。
  Cls
 ⇒ Casio Basic コマンドリファレンス: Cls

最後に、メイン画面の際表示を行うために、メイン画面表示サブルーチン TZM を呼び出します。
  Prog "TZM"


TZS の変更点は、下記のようになります。

サブルーチン:TZS のプログラム (夏時間情報を追加)
Cls
Locate 15,4,"▶t"
Locate 16,4,"E"
Locate 1,4," <Lt-Rt>"   [ これは下へ移動 ]

If M=5:Then
Locate 1,1," DLS IN 2015"
Locate 1,2,"EUR: 3-29⇒10-24"
Locate 1,3,"USA: 3-8 ⇒10-31"◢
Return
Else
If M=6
Then V→Z
Locate 1,1," EUR TIME ZONE"
If S:Then
Locate 1,2,"  WEST  CEST"
Locate 1,3,"  EEST   FEST"
Else
Locate 1,2,"  WET   CET"
Locate 1,3,"  EET    FET"
IfEnd
Else If M=7
Then W→Z
Locate 1,1," USA TIME ZONE"
If T:Then
Locate 1,2," PDT  MDT"
Locate 1,3," CDT  EDT"
Else
Locate 1,2," PST  MST"
Locate 1,2," CST  EST"
IfEnd
IfEnd:IfEnd
IfEnd

Locate 1,4," <Lt-Rt>"    [ これは、上からここへ移動 ]


2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"

Do
Getkey→K
If K=86:Then
Locate X,Y," "
If Z=3:Then 0→Z
Else Z+1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
Else If K=83
Then
Locate X,Y," "
If Z=0:Then 3→Z
Else Z-1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
IfEnd:IfEnd
LoWhile K≠47


(追加部分を赤文字で示す)

・ メニュー番号 M=5 の時の処理として、ヨーロッパとアメリカ(北米)それぞれの夏時間が開始・終了する日時を表示します。
・表示の最後に、◢ 命令を使って、プログラムの実行を一時停止させます。[EXE}キーを押せば一時停止が解除されるので、Returnコマンドで強制的に TZS を終了させ、メインルーチンに戻します。
 ⇒ Casio Basic コマンドリファレンス: ◢ (出力命令)
 ⇒ Casio Basic コマンドリファレンス: Return

なお、M=5 の時、夏時間情報を表示させるので、この時は Locate 1,4," <Tl-Rt>" の表示は邪魔になります。この表示はタイムゾーンを選択させると時に、左矢印と右矢印を使え、と言う操作ガイドなので、M=6M=7 の時のみに必要です。そこで、上に示したように、実行する位置を変更します。





5.時間の再表示

時間の再表示は、サブルーチン TZD で行います。これについては変更の必要がありません。


以上で、プログラムが一応完成しました。




実際に、プログラムを実行していると、いくつか気になる点が出てきたので、最後の仕上げを行います。

ヨーロッパの夏時間か標準時間を切り替えるために、[3] キーを押すとき、1:CEST から 1:CET に表示を切り替わる際に、1:CEST の最後の T の表示がちらつくのが気になったので、以下のように変更しました。

表示サブルーチン TZM の上から2行目;

Locate 1,2,"1:CET"

を、以下のように、スペースを追加しました。

Locate 1,2,"1:CET "


さらに、夏時間と標準時間の切り替えのために [3] キー や [4] キーを押した時、3:ST3:DL の表示の切り替えがもたつく感じがします。 4:ST4:DL の表示の切り替えも同様です。

その原因は、TZM の中で、上記の表示切り替え処理が最後の方にあることにあります。fx-5800P の処理能力が低いためこのようなことになります。そこで、上記の表示の切り替え処理を、メインルーチンの [時間計算]ブロック にある If M=3 および If M=4 の時の処理に、上記の表示切り替えの処理を、敢えて追加します。無駄な処理ですが、これで表示切り替えのモタツキが少し解消しました。

この下に完成したプログラムを示します。今回、追加・修正した部分を赤文字で示しています。

最後に、メインルーチンのプログラム名を TIME ZONE に変更してください。これで完成とします。



完成したプログラム TIME ZONE は、以下の通り(今回追加した部分を赤文字で示す):

メインルーチン:TIME ZONE のプログラム
9→P:17→Q
-1→J:0→G:0→U
0→S:0→T
1→V:0→W
P-V→P:Q-W→Q
Prog "TZM"

While 1

-1→M
Do
Getkey→K
LpWhile K=0
K=25⇒0→M
K=25⇒1→M
K=36⇒2→M
K=37⇒3→M
K=21⇒4→M

0→C
While Getkey=37
Isz C:C=9⇒Break
WhileEnd:C=9⇒5→M
0→C
While Getkey=21
Isz C:C=9⇒Break
WhileEnd:C=9⇒5→M
0→C

While Getkey=35
Isz C:C=9⇒Break
WhileEnd:C=9⇒6→M
0→C
While Getkey=36
Isz C:C=9⇒Break
WhileEnd:C=9⇒7→M

If M=0:Then
8→X:1→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→J
Else If M=1
Then
8→X:2→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→G
Else If M=2:
Then
8→X:3→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→U
Else If M=3 Or M=4
Then
Int(J÷100)→A
J-100A→B
IfEnd:IfEnd
IfEnd:IfEnd

If M=0:Then
A≧24⇒A-24→A
100A+B→J
A-P→C
C<0⇒C+24→C
100C+B→G
A-Q→C
C<0⇒C+24→C
100C+B→U
Else If M=1
Then
A≧24⇒A-24→A
100A+B→G
A+P→C
C≧24⇒C-24→C
100C+B→J
A+P-Q→C
C<0⇒C+24→C
C≧24⇒C-24→C
100C+B→U
Else If M=2
Then
A≧24⇒A-24→A
100A+B→U
A+Q→C
C≧24⇒C-24→C
100C+B→J
A+Q-P→C
C<0⇒C+24→C
C≧24⇒C-24→C
100C+B→G
Else If M=3
Then
If S:Then
0→S:P+1→P
Locate 5,2,"T "
Locate 15,2,"ST"

Else
1→S:P-1→P
Locate 5,2,"ST"
Locate 15,2,"DL"

IfEnd
A-P→C
C<0⇒C+24→C
100C+B→G
Prog "TZM"
Else If M=4
Then
If S:Then
0→T:Q+1→Q
Locate 4,3,"S"
Locate 15,3,"ST"

Else
1→T:Q-1→Q
Locate 4,3,"D"
Locate 15,3,"DL"

IfEnd
A-Q→C
C<0⇒C+24→C
100C+B→U
Prog "TZM"
Else If M=5
Then Prog "TZS"
Cls:Prog "TZM"

Else If M=6
Then Prog "TZS"
Z→V:9-S-Z→P
Int(J÷100)→A
J-100A→B
A-P→C
C<0⇒C+24→C
100C+B→G:Cls
Prog "TZM"
Else If M=7
Then Prog "TZS"
Z→M:17-T-Z→Q
Int(J÷100)→A
J-100A→B
A-Q→C
X<0⇒C+24→C
100C+B→U:Cls
Prog "TZM"
IfEnd:IfEnd
IfEnd:IfEnd
IfEnd:IfEnd
IfEnd:IfEnd

Prog "TZD"

WhileEnd




サブルーチン:TZM のプログラム (画面表示)
Locate 1,1,"0:JST"
Locate 1,2,"1:CET "
Locate 1,3,"2:PST"
Locate 13,2,"3:"
Locate 13,3,"4:"
Locate 1,4,"<AC>:QUIT"

If V=0:Then
Locate 3,2,"W"
Else If V=1
Then Locate 3,2,"C"
Else If V=2
Then Locate 3,2,"E"
Else If V=3
Then Locate 3,2,"F"
IfEnd:IfEnd
IfEnd:IfEnd

If W=0:Then
Locate 3,3,"P"
Else If W=1
Then Locate 3,3,"M"
Else If W=2
Then Locate 3,3,"C"
Else If W=3
Then Locate 3,3,"E"
IfEnd:IfEnd
IfEnd:IfEnd

If S:Then
Locate 5,2,"ST"
Locate 15,2,"DL"
Else
Locate 5,2,"T "
Locate 15,2,"ST"
IfEnd

If T:Then
Locate 4,3,"D"
Locate 15,3,"DL"
Else
Locate 4,3,"S"
Locate 15,3,"ST"
IfEnd




サブルーチン:TZS のプログラム (タイムゾーン設定)
Cls
Locate 15,4,"▶t"
Locate 16,4,"E"

If M=5:Then
Locate 1,1,"  DLS IN 2014"
Locate 1,2,"EUR: 3-30⇒10-26"
Locate 1,3,"USA: 3-9 ⇒11-2"◢
Return
Else
If M=6
Then V→Z
Locate 1,1," EUR TIME ZONE"
If S:Then
Locate 1,2,"  WEST  CEST"
Locate 1,3,"  EEST   FEST"
Else
Locate 1,2,"  WET   CET"
Locate 1,3,"  EET    FET"
IfEnd
Else If M=7
Then W→Z
Locate 1,1," USA TIME ZONE"
If T:Then
Locate 1,2," PDT  MDT"
Locate 1,3," CDT  EDT"
Else
Locate 1,2," PST  MST"
Locate 1,2," CST  EST"
IfEnd
IfEnd:IfEnd
IfEnd

Locate 1,4," <Lt-Rt>"
2+6Z-12Int(Z÷2)→X

2+Int(Z÷2)→Y
Locate X,Y,"⇒"

Do
Getkey→K
If K=86:Then
Locate X,Y," "
If Z=3:Then 0→Z
Else Z+1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
Else If K=83
Then
Locate X,Y," "
If Z=0:Then 3→Z
Else Z-1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
IfEnd:IfEnd
LoWhile K≠47




サブルーチン:TZC のプログラム (時間を「時」と「分」に分離):変更なし
If Z<100:Then
Z→X:0→Y
Else
Int(Z÷100)→X
Z-100X→Y
IfEnd




サブルーチン TZD のプログラム (時間の表示):変更なし
J=-1⇒Return

Locate 8,1,"0000"
J⇒Locate 11-Int(log(J)),1,J
Locate 8,2,"0000"
G⇒Locate 11-Int(log(G)),2,G
Locate 8,3,"0000"
U⇒Locate 11-Int(log(U)),3,U




世界の時差換算プログラム TIME ZONE が完成しました。

「入力ボックス」は、以下にあります。
 ⇒ プログラムライブラリ - 入力ボックス

今回 fx-5800P 用に作ったものは、プログラムライブラリ - Time Zone にもまとめています。
このプログラムを fx-9860GII や fx-CG20 に移植したものは、こちら のプログラムライブラリにまとめていて、プログラムファイルをダインロードして電卓に転送してすぐに使えます。


次回からは、入力ボックスの高速化と、正負全小数へ対応するための拡張を試みます。



つづく...

Casio Basic入門32 / 目次




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

人気ブログランキングへ


FC2ブログランキングへ



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

商品詳細を見る



keywords: fx-5800PCasioBasic、世界時間換算, プログラミング入門プログラム関数電卓

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



関連記事

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

Casio Basic入門30

Casio Basic入門
<目次>

誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
最終更新: 2015/01/24

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

Chapter 5

◆ Chapter 5 の目標: サブルーチンを使いこなす

前回: Casio Basic入門29 を見る


前回は、ヨーロッパのタイムゾーンを変更・設定する機能を詳細にみてみました。

今回は、アメリカのタイムゾーンを変更・設定する機能を追加してゆきます。

今回完成させるプログラムを一番下に掲載しているので、先にそれを見て分かれば、先へ進むのも良いでしょう。



Chapter5-8
類似処理による機能追加

39-TZ5_main 

このメイン画面では、2:PST は、アメリカの太平洋標準時間を示しています。

アメリカにあるタイムゾーンのうち、下記の4つのタイムゾーンに切り替えられるように機能を追加してゆきます。

タイムゾーン標準時間 夏時間 
太平洋時間PSTPDT
山岳部時間MSTMDT
中部時間CSTCDT
東部時間ESTEDT

US-TZ  
Time-J.net 世界時計 - 世界の時間と時差 - アメリカの時差と現在時刻 から引用


ここで [2] キーを長押しすると、下に示すような 「アメリカのタイムゾーン選択画面」を表示させることにします。

44-TZSelect_NA 

ここでの操作は、ヨーロッパのタイムゾーン設定と全く同様にします。

つまり、左矢印キー [◀] か 右矢印キー [▶] を押すと、⇒ マークが移動し、[EXE] キーを押すと ⇒ マークで示されているタイムゾーンが確定されるようにします。この追加はタイムゾーン設定サブルーチン TZS に追加します。

北米のタイムゾーン変数として、新たに変数 W を使い、夏時間フラグ T と合わせて、以下のように決めます。

タイムゾーン標準時間 (T=0)夏時間 (T=1) 変数 W の値
太平洋時間PSTPDT0
山岳部時間MSTMDT1
中部時間CSTCDT2
東部時間ESTEDT3

サブルーチン TZS でアメリカのタイムゾーンを設定した場合は、変数 W の値を変更します。

TZS が終了してメインルーチンに戻ってきたら、必要な時間計算を行い、最後に時間表示サブルーチン TZD を呼び出して、変数 W の値に従って、時間表示サブルーチン TZD で時間表示を更新します。

以上が今回の機能追加の内容で、具体的には以下のように進めます。

1.初期化処理
新たに、アメリカのタイムゾーン変数 W を追加する。それに合わせて変数を初期化する。
メイン画面表示サブルーチン TZM にもアメリカの異なるタイムゾーン略称を表示するように機能追加する。

2.メニュー番号取得処理
今回は、[2] キーの長押しを検出し、検出されたときに、メニュー変数 M に 7 を入れる。

3.入力処理
M=7 の時は、キー入力処理は行なわない。但し、アメリカのタイムゾーン変更に伴って、メイン画面のタイムゾーン表示を変更するために、メイン画面表示サブルーチン TZM を呼び出す(これに合わせて TZM を修正する)。

4.時間の計算
M=7 の時、タイムゾーン変更に合わせて北米時間を計算する。日本時間とヨーロッパ時間には影響が無いので、これらの計算は行わない。

5.時間表示の更新
時間表示サブルーチン TZD を用いて、日本時間、ヨーロッパ時間、アメリカ時間の表示を更新する。

6.ループ構造
既にある While 1 ~ WhileEnd ループの中に、上記追加コードを入れる。


メインルーチンの擬似的なプログラムは、以下になります。追加・修正するところが分かると思います。


[初期化処理]

Prog "TZM"  [メイン画面表示]

While 1

  [メニュー番号取得処理]

  
[ [1]  および [2] キー長押しを検出し それぞれメニュー番号 M=6, 7 とする処理]

  If M=0:Then
    [日本時間入力処理] (時間から「時」と「分」の分離も行う)
  Else If M=1:Then
    [ドイツ時間入力処理] (時間から「時」と「分」の分離も行う)
  Else If M=2:Then
    [LA時間入力処理] (時間から「時と「分」の分離も行う)
  Else If M=3:Then
    キー入力処理は行わない。時間から「時」と「分」の分離のみ行う
  Else If M=4:Then
    キー入力処理は行わない。時間から「時」と「分」の分離のみ行う
  IfEnd:IfEnd
  IfEnd:IfEnd
  IfEnd

  If M=0:Then
    [時間計算]
  Else If M=1:Then
    [時差計算]
  Else If M=2:Then
    [時間計算]
  Else If M=3:Then
    [時間計算]
  Else If M=4:Then
    [時間計算]
  
Else If M=6:Then
    Prog "TZS"  
[ヨーロッパタイムゾーン設定]
    [時間計算]
    Prog "TZM"  
[メイン画面表示]
  
Else If M=7:Then
    Prog "TZS"  
[アメリカタイムゾーン設定]
    [時間計算]
    Prog "TZM"  
[メイン画面表示]

  IfEnd:
IfEnd
  IfEnd:IfEnd
  IfEnd:IfEnd
  IfEnd

  
Prog "TZD"    [時間の再表示]

WhileEnd


(赤文字は機能追加部分)



1.初期化処理
プログラム起動時に、太平洋時間を表示させたいと言う私の好みから、北米のタイムゾーン変数 W を 0 で初期化しておき、Q と W から Q の初期値を太平洋時間に設定します。
1→W
Q-W→Q

を追加します。

次に、初期表示を受け持っているサブルーチン TZM をアメリカの複数タイムゾーンに対応するように修正します。 TZM 修正内容は以下で説明します。



2.メニュー番号取得処理 - キー長押し処理


[2] キー長押しを検出して、メニュー変数 M7 を入れます。

長押し検出は、既に説明したものを [2] に対応したものを追加するだけです。

メニュー番号取得処理のソースコード
-1→M
Do
Getkey→K
LpWhile K=0
K=25⇒0→M
K=35⇒1→M
K=36⇒2→M
K=37⇒3→M
K=21⇒4→M

0→C
While Getkey=35
Isz C
C=9⇒Break
WhileEnd
C=9⇒6→M
0→C
While Getkey=36
Isz C
C=9⇒Break
WhileEnd
C=9⇒7→M


(赤文字は追加部分)



3.入力処理

入力処理を行わないので、[入力処理ブロック] には何もプログラムを書きません。



4.時間計算

先ず、タイムゾーン設定サブルーチン TZS を呼び出します。TZS はタイムゾーン変数 Z に 0、1、2、3 のいずれかの値を入れてから終了します。今回は、サブルーチン TSZ にアメリカのタイムゾーン選択に関する部分を追加します。TZS 変更については、以下で説明します。

次に、TZS が設定した変数 Z に基づいて、メインルーチンの北米タイムゾーン変数 W を設定し、北米時差変数 Q を算出します。そして、時差 Q から時間を計算します。

最後に、メイン画面表示サブルーチン TZM を呼び出して、選んだタイムゾーンに合わて画面を再表示します。TZM の変更点は、以下で説明しますす。


メインルーチンの [時間計算] ブロック に追加するプログラムを示します。今回変更するメインルーチン全体は、一番下に掲載しています。

メインルーチンに追加するプログラム
Else If M=7
Then Prog "TZS"
Z→W:17-S-Z→Q
Int(J÷100)→A
J-100A→B
A-Q→C
C<0⇒C+24→C
100C+B→U
Cls
Prog "TZM"
IfEnd


タイムゾーン設定サブルーチン TZS を呼び出します。TZS の変更点は、以下で説明します。
  Prog "TZS"

変数 Z は使い捨て変数で、プログラムの動作中にその値が変化しても良いように使っている変数です。一方、変数 W はヨーロッパのタイムゾーン値を格納する予約変数として使っていて、その値は勝手に変更されては困ります。
そこで、TZS の直後で、Z の値を W に入れます。続いて、ヨーロッパ時差の変数 Q を計算します。ここでは夏時間も考慮して、夏時間フラグ T も使います。アメリカの西の端、つまり太平洋時間の時差は、日本からみて17時間です。夏時間では時差が1時間減るので、タイムゾーン値を引き算すれば、選択したタイムゾーンの時差が分かります。
  Z→W:17-T-Z→Q

タイムゾーンを変更しても、日本時間は変わりません。そこで、日本時間を基準に、時差 Q から、選択したタイムゾーンの時間を計算します。現在の日本時間 J から「時」: A と 「分」: B を算出します。この計算は、既に他でも行っているのと同じです。
  Int(J÷100)→A
  J-100A→B


選択したタイムゾーンの時差が Q なので、A - Q が、その地域の「時」になります。但しこの結果が負になる場合があって、まだ前日であることを意味します。そこで、A - Q が 0 未満の時は 24 を加えると正しい時間になります。この計算も、、これまでに行っているのと同じです。
  A-Q→C
  C<0⇒C+24→C


選んだタイムゾーンの「時」: C が分かったので、アメリカ時間 U が計算できます。これも、これまでに行っているのと同じです。
  100C+B→U

プログラムがここまで進んできても、タイムゾーン設定画面が表示されたままです。そこで、Cls コマンドで画面を消去します。
  Cls
 ⇒ Casio Basic コマンドリファレンス: Cls

最後に、メイン画面の際表示を行うために、メイン画面表示サブルーチン TZM を呼び出します。
  Prog "TZM"


TZS を、アメリカの4つのタイムゾーンに合わせて変更します。
太平洋時間(ロサンゼルス)の夏時間への対応は既に済んでいて、以下のような別のタイムゾーンの略称に対しても、夏時間への対応部分はそのまま使えます。

タイムゾーン標準時間 夏時間 変数 W の値
太平洋時間PSTPDT0
山岳部時間MSTMDT1
 中央部時間CSTCDT2
東部時間ESTEDT3

タイムゾーンが変われば、略称の1文字目を変更すれば良く、標準時間と夏時間の両方に対応できることが分かります。
そこで、W の値に応じて、赤く示したアルファベットのみを Locate コマンドで上書きします。

画面表示サブルーチン TZM のプログラム
Locate 1,1,"0:JST"
Locate 1,2,"1:CET"
Locate 1,3,"2:PST"
Locate 13,2,"3:"
Locate 13,3,"4:"
Locate 1,4,"<AC>:QUIT"

If V=0:Then
Locate 3,2,"W"
Else If V=1
Then Locate 3,2,"C"
Else If V=2
Then Locate 3,2,"E"
Else If V=3
Then Locate 3,2,"F"
IfEnd:IfEnd
IfEnd:IfEnd

If W=0:Then
Locate 3,3,"P"
Else If W=1
Then Locate 3,3,"M"
Else If W=2
Then Locate 3,3,"C"
Else If W=3
Then Locate 3,3,"E"
IfEnd:IfEnd
IfEnd:IfEnd


If S:Then
Locate 5,2,"ST"
Locate 15,2,"DL"
Else
Locate 5,2,"T "
Locate 15,2,"ST"
IfEnd

If T:Then
Locate 4,3,"D"
Locate 15,3,"DL"
Else
Locate 4,3,"S"
Locate 15,3,"ST"
IfEnd


(追加部分は赤文字


タイムゾーン設定サブルチン TZS の変更

前回つくった、ヨーロッパのタイムゾーンを変更する TZS のプログラムを示します。ココに、今回追加する部分を赤文字で追加してみます。

Cls
Locate 15,4,"▶t"
Locate 16,4,"E"
Locate 1,4," <Lt-Rt>"

If M=6
Then V→Z
Locate 1,1," EUR TIME ZONE"
If S:Then
Locate 1,2,"  WEST  CEST"
Locate 1,3,"  EEST   FEST"
Else
Locate 1,2,"  WET   CET"
Locate 1,3,"  EET    FET"
IfEnd
Else If M=7
Then W→Z
Locate 1,1," USA TIME ZONE"
If T:Then
Locate 1,2," PDT  MDT"
Locate 1,3," CDT  EDT"
Else
Locate 1,2," PST  MST"
Locate 1,2," CST  EST"
IfEnd
IfEnd:IfEnd

2+6Z-12Int(Z÷2)→X

2+Int(Z÷2)→Y
Locate X,Y,"⇒"

Do
Getkey→K
If K=86:Then
Locate X,Y," "
If Z=3:Then 0→Z
Else Z+1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
Else If K=83
Then
Locate X,Y," "
If Z=0:Then 3→Z
Else Z-1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
IfEnd:IfEnd
LoWhile K≠47



・ メニュー番号 M=7 の時の処理として、アメリカのタイムゾーンの一覧表示を追加します。
・それ以外の処理は、既に作ったものをそのまま使えます...実際は、そのまま使えるように予め考えていたと言うのが正しいのですが...



5.時間の再表示

時間の再表示は、サブルーチン TZD で行います。これについては変更の必要がありません。

サブルーチン TZD のプログラム: 変更なし
J=-1⇒Return

Locate 8,1,"000"
J⇒Locate 11-Int(log(J)),1,J
Locate 8,2,"0000"
G⇒Locate 11-Int(log(G)),2,G
Locate 8,3,"0000"
U⇒Locate 11-Int(log(U)),3,U




今回までに作成したプログラムは、以下の通り(今回追加した部分を赤文字で示す):

メインルーチン:TZ のプログラム
9→P:17→Q
-1→J:0→G:0→U
0→S:0→T
1→V:0→W
P-V→P:Q-W→Q
Prog "TZM"

While 1

-1→M
Do
Getkey→K
LpWhile K=0
K=25⇒0→M
K=25⇒1→M
K=36⇒2→M
K=37⇒3→M
K=21⇒4→M

0→C
While Getkey=35
Isz C:C=9⇒Break
WhileEnd:C=9⇒6→M
0→C
While Getkey=36
Isz C:C=9⇒Break
WhileEnd:C=9⇒7→M


If M=0:Then
8→X:1→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→J
Else If M=1
Then
8→X:2→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→G
Else If M=2:
Then
8→X:3→Y:4→D:1→E
Prog "INPI"
Prog "TZC"
X→A:Y→B:Z→U
Else If M=3 Or M=4
Then
Int(J÷100)→A
J-100A→B
IfEnd:IfEnd
IfEnd:IfEnd

If M=0:Then
A≧24⇒A-24→A
100A+B→J
A-P→C
C<0⇒C+24→C
100C+B→G
A-Q→C
C<0⇒C+24→C
100C+B→U
Else If M=1
Then
A≧24⇒A-24→A
100A+B→G
A+P→C
C≧24⇒C-24→C
100C+B→J
A+P-Q→C
C<0⇒C+24→C
C≧24⇒C-24→C
100C+B→U
Else If M=2
Then
A≧24⇒A-24→A
100A+B→U
A+Q→C
C≧24⇒C-24→C
100C+B→J
A+Q-P→C
C<0⇒C+24→C
C≧24⇒C-24→C
100C+B→G
Else If M=3
Then
If S:Then
0→S:P+1→P
Else
1→S:P-1→P
IfEnd
A-P→C
C<0⇒C+24→C
100C+B→G
Prog "TZM"
Else If M=4
Then
If S:Then
0→T:Q+1→Q
Else
1→T:Q-1→Q
IfEnd
A-Q→C
C<0⇒C+24→C
100C+B→U
Prog "TZM"
Else If M=6
Then Prog "TZS"
Z→V:9-S-Z→P
Int(J÷100)→A
J-100A→B
A-P→C
C<0⇒C+24→C
100C+B→G:Cls
Prog "TZM"
Else If M=7
Then Prog "TZS"
Z→M:17-T-Z→Q
Int(J÷100)→A
J-100A→B
A-Q→C
X<0⇒C+24→C
100C+B→U:Cls

Prog "TZM"
IfEnd:IfEnd
IfEnd:IfEnd
IfEnd:IfEnd
IfEnd

Prog "TZD"

WhileEnd




サブルーチン:TZM のプログラム (画面表示)
Locate 1,1,"0:JST"
Locate 1,2,"1:CET"
Locate 1,3,"2:PST"
Locate 13,2,"3:"
Locate 13,3,"4:"
Locate 1,4,"<AC>:QUIT"

If V=0:Then
Locate 3,2,"W"
Else If V=1
Then Locate 3,2,"C"
Else If V=2
Then Locate 3,2,"E"
Else If V=3
Then Locate 3,2,"F"
IfEnd:IfEnd
IfEnd:IfEnd

If W=0:Then
Locate 3,3,"P"
Else If W=1
Then Locate 3,3,"M"
Else If W=2
Then Locate 3,3,"C"
Else If W=3
Then Locate 3,3,"E"
IfEnd:IfEnd
IfEnd:IfEnd


If S:Then
Locate 5,2,"ST"
Locate 15,2,"DL"
Else
Locate 5,2,"T "
Locate 15,2,"ST"
IfEnd

If T:Then
Locate 4,3,"D"
Locate 15,3,"DL"
Else
Locate 4,3,"S"
Locate 15,3,"ST"
IfEnd




サブルーチン:TZS のプログラム (タイムゾーン設定)
Cls
Locate 15,4,"▶t"
Locate 16,4,"E"
Locate 1,4," <Lt-Rt>"

If M=6
Then V→Z
Locate 1,1," EUR TIME ZONE"
If S:Then
Locate 1,2,"  WEST  CEST"
Locate 1,3,"  EEST   FEST"
Else
Locate 1,2,"  WET   CET"
Locate 1,3,"  EET    FET"
IfEnd
Else If M=7
Then W→Z
Locate 1,1," USA TIME ZONE"
If T:Then
Locate 1,2," PDT  MDT"
Locate 1,3," CDT  EDT"
Else
Locate 1,2," PST  MST"
Locate 1,2," CST  EST"
IfEnd
IfEnd:IfEnd

2+6Z-12Int(Z÷2)→X

2+Int(Z÷2)→Y
Locate X,Y,"⇒"

Do
Getkey→K
If K=86:Then
Locate X,Y," "
If Z=3:Then 0→Z
Else Z+1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
Else If K=83
Then
Locate X,Y," "
If Z=0:Then 3→Z
Else Z-1→Z
IfEnd
2+6Z-12Int(Z÷2)→X
2+Int(Z÷2)→Y
Locate X,Y,"⇒"
IfEnd:IfEnd
LoWhile K≠47




サブルーチン:TZC のプログラム (時間を「時」と「分」に分離):変更なし
If Z<100:Then
Z→X:0→Y
Else
Int(Z÷100)→X
Z-100X→Y
IfEnd




サブルーチン TZD のプログラム (時間の表示):変更なし
J=-1⇒Return

Locate 8,1,"0000"
J⇒Locate 11-Int(log(J)),1,J
Locate 8,2,"0000"
G⇒Locate 11-Int(log(G)),2,G
Locate 8,3,"0000"
U⇒Locate 11-Int(log(U)),3,U




今回は、アメリカのタイムゾーンを変更できるように、機能追加を行いました。
次回は、ヨーロッパやアメリカのタイムゾーンの開始と終了日時を表示する機能を追加します。



つづく...


Casio Basic入門31 / 目次




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

人気ブログランキングへ


FC2ブログランキングへ



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

商品詳細を見る



keywords: fx-5800PCasioBasic、世界時間換算, プログラミング入門プログラム関数電卓

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



関連記事

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

fx-5800P:変数アクセス、比較・論理演算、条件分岐の速度比較

追記: 2014年12月13日

fx-5800PCasio Basic でプログラムを書いていると、コマンドや命令の使い方で、処理速度が大きく異なることに気づきます。

条件分岐(If 文や ⇒ 命令)、ループ (Do、While For)については以前調べています。
 ⇒ fx-5800P コマンドの処理速度【再編集】


fx-5800P の Casio Basic では配列変数を使えて便利ですが、これを使うと処理速度が大きく低下することが経験的に分かっています。

そこで、配列変数と同様な使い方のできるリストと行列を含めて、これらの処理速度を調べてみます。比較のために通常変数も併せて調べます。

fx-5800P 搭載の Casio Basic には、プログラムで変数として使えるものに、以下があります。
 ・通常変数: AZ の 26 個
 ・配列変数: Z[ ]
 ・リスト: List X[ ]List Y[ ]Freq[ ] (要素数は最大199)
 ・行列: Mat A[ ] (行列名に AZ が使える、要素数は、行・列それぞれ最大10)

論理演算(And、Or、Not)も体感的に重い処理だと分かっているので、比較演算(=、≠、<、>、≦、≧)と合わせて速度を調べてみます。



測定方法

測定し易いようにループで1000回実行させ、スマートフォンのストップウォッチアプリで、時間を計ります。
測定用のプログラム ST (Speed Test) は、以下のようにします。

・プログラム名ST xxxx (xxxx は計測対象が分かるような表現にする)

・プログラム
[必要な初期設定]
1000→A
"ST:xxxx"◢
Lbl 0
[測定対象]
Dsz A
Goto 0

必要な初期設定の後、出力命令  でプログラムは一旦停止。[EXE] キーを押すと同時にストップウォッチをスタート。
ループが1000回まわって、プログラムが終了すると画面表示が変わるので、そのタイミングでストップウォッチを止める。

但し、fx-5800P を使っていて、処理速度の個体差や、バッテリーLOW時の速度低下(電池を入れ替えると速度が上がる)などでの速度差を体感しています。さらに、fx-5800P ではクロック発生用に比較的精度のある発振子使っていない可能性があり、クロックが環境条件や電池の電圧の影響を受ける可能性がある、との情報を頂いております。⇒ sentaro様のコメント

従って、ここでの測定値は絶対値として評価することに意味はありません。基準ループとの相対的な処理時間差に着目し、その目安として測定値(ミリ秒)を用いることにします。

測定は5回行って、最大値と最小値を外し、残り3つの値の平均を計算して測定結果とします。なお私の反射神経では、小数点一桁目までは比較的再現性が高いことから、小数点1桁目までを有効数字として使い、小数2桁以下は切り捨てます。



基準ループ

1000→A
"ST: L-G"◢
Lbl 0
Dsz A
Goto 0


基準ループ測定結果: 5.9

以前、fx-5800P コマンドの処理速度【再編集】 では、上記のプログラムの最後に "DONE"◢ があります。そこでこの表示を加えたものを今回測定すると、6.1 秒 でした。以前の記事を書いた時の測定時結果が 6 秒で、前回と今回の速度差は、"DONE"◢ 表示によるものと考えらます。今回の測定での表示による速度差が 0.2 秒 なので、fx-5800P のクロック変動および測定誤差を考えると、今回の基準ループの測定結果は妥当と考えて良さそうです。

前回測定 (秒)今回測定 (秒)
"DONE"◢ 有り66.1
"DONE"◢ 無し---5.9

さて、測定対象を含んだプログラムの測定結果から基準ループ測定結果を引き算して、測定対象の処理時間を求めます。
[測定結果 (秒)] - 5.9 秒 = [測定対象の処理時間 (秒)]

これは、1000回繰り返した結果なので、1000 で割って一回あたりの処理時間 (ミリ秒) を計算します。



通常変数

先ずは、通常変数のアクセス速度を調べます。

1000→A:0→B
"ST:B"◢
Lbl 0
A→B
Dsz A
Goto 0


測定結果: 11.3 秒

[測定結果] - [基準ループ測定値] = [目的の処理時間] なので、
通常変数アクセス時間: 11.3 - 5.9 = 5.4 秒
これは、1000回実行した時の時間なので、

通常変数アクセス時間: 5.4 ミリ秒



配列変数

配列変数からの読み出しと書き込みの両方を調べました。

配列変数読み出し
0→DimZ
10→DimZ
1000→A:0→B
"ST:Z[ ] READ"◢
Lbl 0
Z[2]→B
Dsz A
Goto 0


測定結果: 28.6 

配列変数読出し時間: 28.7 ミリ秒


配列変数書き込み
0→DimZ
10→DimZ
1000→A
"ST:Z[ ] WRITE"◢
Lbl 0
A→Z[2]
Dsz A
Goto 0


測定時間: 27.9 ミリ秒

配列変数書込み時間: 22.0 ミリ秒

配列変数は、読み出しよりも書き込みが若干速いようです。これは予想外です。
配列変数へのアクセスは、通常変数の4倍弱の時間がかかることが分かりました。
速度を要求するところでは、配列変数へのアクセスを極力減らすべきです。



リスト

Casio Basic には、統計計算を行うために List が用意されています。
List は、1項目あたり、List X[ ]List Y[ ]List Freq[ ] と3つの配列が対応し、それぞれの配列の要素数は最大199です。
言い換えれば、1つの要素インデックス K に対して、List X[K]List Y[K]Freq[K] の3つの配列が使えるので、便利そうです。

XYFreq いずれも処理速度は同じと思われるので、測定には List X[ ] を使い、読み出しと書込の両方を調べました。

List 読み出し
ClrStat
{0,0,0,0,0,0,0,0,0,0}→List X
1000→A:0→B
"ST:LIST READ"◢
Lbl 0
List X[2]→B
Dsz A
Goto 0


測定結果: 31.0 秒

リスト読み出し時間: 25.1 ミリ秒


List 書き込み
ClrStat
{0,0,0,0,0,0,0,0,0,0}→List X
1000→A
"ST:LIST WRITE"◢
Lbl 0
A→List X[2]
Dsz A
Goto 0


測定結果: 31.2 秒

List 書き込み時間: 25.3 ミリ秒


List は、読み出しより書き込みに時間がかかるようです。
List へのアクセス時間は、配列変数よりも少し時間を要することが分かりました。
List の利便性は魅力がありますが、List を使うくらいなら、配列変数を使った方が少しは処理が速いことが分かります。


いずれにせよ、高速処理が必要なところでは List へのアクセスを最小限に抑えるのが良いことが分かります。



行列

fx-5800P の Casio Basic では正式に行列をサポートしていませんが、実際は使えます。
行要素、列要素それぞれ最大10です。言い換えれば、最大で、要素10の10次元配列が使えるわけで、処理内容に応じては大変便利なものです。行列についても、読み出しと書き込みの両方で測定しました。

行列読み込み
ClrMat
[[0,0,0,0,0,0,0,0,0,0]]→Mat A
1000→A:0→B
"ST:MAT READ"◢
Lbl 0
Mat A[1,2]→B
Dsz A
Goto 0


測定結果: 32.8 秒

行列読み出し時間: 26.9 ミリ秒


行列書き込み
ClrMat
[[0,0,0,0,0,0,0,0,0,0]]→Mat A
1000→A
"ST:MAT WRITE"◢
Lbl 0
A→Mat A[1,2]
Dsz A
Goto 0


測定結果: 34.3 秒

行列書き込み時間: 28.4 ミリ秒


行列は、読み出しよりも書き込みに若干時間がかかるようです。
行列のアクセス時間は、List よりもさらに時間がかかることが分かります。
速度を要求する場合は、どうしても必要性がある場合を除いて、使わないのが良いことが分かります。


以上、配列として使える、配列変数、リスト、行列 について調べた結果は、通常変数に比べて4倍程度のアクセス時間がかかることが分かり、速度を要求する場合には、極力アクセス数を減らすようなプログラムの書き方が必要なことが、明確になりました。



続いて、論理演算と比較演算の処理速度を調べます。

論理演算

fx-5800P の論理演算子には、And、Or、Not があります。いずれの処理速度も同等だと考え、測定には And を使います。

1000→A:0→B
"ST:LOGIC"◢
Lbl 0
A And B
Dsz A
Goto 0


測定結果: 15.9 秒

論理演算処理時間: 10.0 ミリ秒

論理演算1回だけの処理時間としては、短いとも長いとも言えないでしょう。しかし論理演算を多用すると、プログラムの実行速度が大きく損なわれることが分かりました。速度を要求する場合は、論理演算を極力控えた方がよさそうです。



比較演算

fx-5800P の Casio Basic の比較演算子には、=<> があります。
いずれの処理速度も同等だと考え、測定には を使い、[変数]≠[変数]、と [変数]≠[数値] の測定を行います。

変数との比較演算
1000→A:0→B
"ST:COMP B"
Lbl 0
A≠B
Dsz A
Goto 0


測定結果: 15.6 秒

変数との比較演算時間: 9.7 ミリ秒


数値との比較演算
1000→A
"ST:COMP 2"◢
Lbl 0
A≠2
Dsz A
Goto 0


測定結果: 17.4 秒

数値との比較演算時間: 11.5 ミリ秒


変数との比較演算よりも数値との比較演算に時間がかかるのは、興味深い結果です。
比較演算を行う時は、即値(数値)を使うのではなく、変数を利用するほうが処理が速くなることが分かります。

論理演算で即値を使うケースとしては、If A=0 といった処理をよく使います。
この場合は、0→C としておき、If A=C とする方が処理が速いわけで、条件分岐を多く使う場合は特に効果があります。
一方、If A≠0 とする場合は、迷わず If A とすべきでしょう。



そこで、一連の測定を行ったついでに、同じ環境条件、電池消耗条件で、If 文の処理速度も測定してみて、今回の一連の測定結果の中で、相対的にどの位置にくるのかを調べてみます。

If A≠B

1000→A:0→B
"ST:ID A B"◢
Lbl 0
If A≠B:Then
Dsz A
Goto 0

IfEnd


測定結果: 17.9 秒

If A≠B の処理時間: 12.0

この処理時間には、比較演算 A≠B が含まれているので、変数との比較演算の 9.7 ミリ秒がこの処理の多くを占めていることが分かります。


If A≠0

1000→A
"ST:IF A 0"◢
Lbl 0
If A≠0:Then
Dsz A
Goto 0

IfEnd


測定結果: 19.6 秒

If A≠0 の処理時間: 13.7 ミリ秒

B=0 の B を使ったIf 文よりも 即値 0 を使った If 文の方が 1.7ミリ秒時間がかかりますが、比較演算の変数と即値での違いの 1.8 ミリ秒に近いことが分かります。If 文では、変数を使った速い比較演算を行う方が良いことが明かです。 これは、面白い結果です。


If A

ここまでみてくると、変数が真が偽かの判定のみの場合が気になります。

1000→A
"ST:IF A"◢
Lbl 0
If A:Then
Dsz A
Goto 0

IfEnd


測定結果: 12.1 秒

If A の処理時間: 6.2 ミリ秒


比較演算を使わないと、処理速度が大幅に向上することが、今回も確認されました。


A⇒

If A よりも A⇒ の処理が速いことは既に分かっています。今回の一連の測定で、相対的にどの位置に来るのか調べて見ました。

1000→A
"ST:JUMP"◢
Lbl 0
Dsz A

A⇒
Goto 0


測定結果: 10.0 秒

A⇒ の処理時間: 4.1 ミリ秒

とても速い結果となりました。比較演算がなく、さらに IfEndへのラベル検索動作も無いことが、この結果を説明するのだと思います。


A≠B⇒ [2014/12/13 追記]

では比較演算式と条件分岐 ⇒ の組み合わせは、どうなるでしょうか?

1000→A:0→B
"ST:COMP JUMP"◢
Lbl 0
Dsz A

A≠B⇒Goto 0


測定結果: 15.9 秒

A≠B⇒ の処理時間: 10ミリ秒

比較演算が含まれますが、それでも If A≠B よりも 2 ミリ秒速いことが分かりました。条件分岐した結果の処理がコマンド/命令1つの場合は、A≠B⇒ を使う方が処理が速いことが分かります。


If A Else

1000→A:0→B
"ST:IF A ELSE"◢
Lbl 0
If A:Then

Dsz A
Goto 0

Else
IfEnd


測定結果: 13.1 秒

If A Else の処理時間: 7.2 ミリ秒

条件ジャンプ命令 を2つ使うよりも、If A Else を使った方が、間違いなく速いことが分かります。



テキスト表示 [2014/12/12 追記]

ダイナミックに数値の変化を表示するような場合は、表示速度のプログラム全体への影響が大きくなります。そこで Locate コマンドによる表示の速さを測定してみます。

1000→A
"ST:Locate"◢
Lbl 0
Locate 1,2,A
Dsz A
Goto 0


測定結果: 26.3 秒

Locate の処理時間: 20.4 ミリ秒

今回評価した中で、Locate コマンドによるテキスト表示は相対的に重い処理であることが分かります。



今回の結果を表にまとめます。

これまで感覚的に思っていたことの定量的な裏付けがとれました。
今後はこれを参考にして、速い処理が必要な時の指針にしようと思います。

表 fx-5800P Casio Basic 処理時間の比較
処理内容処理時間 (ミリ秒)
A⇒4.1
通常変数アクセス5.4
If A6.2
If A Else7.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
※ 処理時間は、基準ループからの相対差で得られたもので、絶対値に厳密性はありません。


[2014/12/12 追記]
今回作った測定用ルーチンを、全て1つのプログラムファイルにまとめて実行させるとどうなるか?
先ず、Lbl / Goto は、各測定ルーチンごとに、異なる番号を指定する必要があります。

Lbl 0 / Goto 0
Lbl 1 / Goto 1
Lbl 2 / Goto 2
   ・
   ・
   ・

試しにやってみました。
すると、予想通りに基準ループの測定値(本来 5.9 秒) が3倍に増えました。

Lbl / Goto は fx-5800P では最も速いループ構造ではありますが、Goto によりラベルを探すのにそれ相当の時間がかかっているので、探すラベルの数が増えれば目に見えて余計に時間がかかります。

Lbl / Goto を多用すると、ラベル検索のために大幅な処理速度の低下に繋がることが確認されました。

私自身、ついつい忘れそうなので、追記しておきます。





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

人気ブログランキングへ


FC2ブログランキングへ



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

商品詳細を見る



keywords: fx-5800P、プログラミングCasioBasicプログラム関数電卓

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


関連記事

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

fx-9860GII USB POWER GRAPHIC 2

2014年12月09日
2015年1月13日 追記


やっぱり fx-5800P が好き

5800と9860、外観 

fx-9860GII と fx-5800P を並べてみる。このくらい違う。厚みが倍近いので、fx-5800P の一回り大きいのが fx-9860GII。やはり、持ち歩くなら fx-5800P のほうが良いと思います。小型・軽量・十分な機能を備えているからです。


関数電卓として

fx-5800P の方が、ひと押しで使える関数キーが多いので、一見 fx-5800P が良いように思えますが、これは慣れの問題だと思います。

ところで、

235÷658

と入力して [EXE] キーを押すと、

fx-9860GII は、0.3571428571 と表示し、[F-D] キーを押すと、5/14 と分数表示になります。
fx-5800P は、5/14 と先ず表示し、[S-D] キーを押すと 0.3571428571 と表示が変わります。

電卓で計算する時、欲しいのは小数であって、分数でないことが殆どです。fx-9860GII の方が優れていると言えます。


5800と9860、複素数 

上の写真の両機の画面を見てください。πi  を計算させようとしています。

この は複素指数関数で、複素数計算を非常に楽にしてくれる便利モノです(大学理工系で出てくると思います)。

 e(a+bi) = (cos b + i sin b)

例えば、a = 0、b = π の場合は、π = -1 と言う「オイラーの恒等式」が得られます。映画「博士の愛した数式」で有名になったものですね。

私が知っている範囲の国産のスタンダード関数電卓やプログラム関数電卓で、これを正しく計算できるものはこれまで見たことがありませんでした。グラフ関数電卓はワンランク上なのですね(グラフ関数電卓を初めて触った感想)。

左の fx-5800P は、a + bi 形式や極形式の複素数計算はできますが、このような複素指数関数を使って、このまま [EXE] キーを押すとエラーになって計算できません。

ところが、fx-9860GII ではこれを計算でき、正しく -1 と結果がでました。これは、チョット感動モノです。
(5/3)π を計算させると、1/2 - (√3/2)i と正しく答えが得られます。


プログラム電卓として

さて、両機ともプログラミング言語として Casio Basic が使えます。fx-5800P の Casio Basic で作ったプログラムの幾つかを fx-9860GII に移植していますが、比較的移植性は高いと言えます。

 ⇒ プログラムライブラリ - キーコード取得
 ⇒ fx-9860GII への移植 - ピタゴラス数
 ⇒ fx-9860GII への移植 - 素因数素分解
 ⇒ fx-9860GII への移植 - 厄介な旧来の命令

[2015/01/13 追記]
Casio Basic は、古くからのカシオのプログラム電卓との互換性を保つための旧来の命令とBasicコマンドから成り立っています。Basic命令については fx-5800P との互換性は非常に高いと言えますが、旧来の命令については細かいところで fx-5800P との互換性が崩れています。但し対処方法はあります(上記の移植に関する記事参照)。詳細に見てゆくと旧来の命令とBasicコマンドが最もバランス良く実装されているのが fx-5800P と言えます。

fx-9860GII でプログラムを走らせる最大の利点が、その処理速度でしょう。加えて、文字列が扱えること、I/O機能、プログラムのPCへの保存機能なども fx-9860GII の利点です。

fx-9860GII は C言語開発SDK を使ってPCで作ったアドイン・プログラムを転送して使えます。Casio Basic では出来ないことが、C言語で出来るし、同じプログラムなら C で書いた方が動作が格段に速くなります。これも利点の1つでしょう。

ちなみに、fx-9860GII は、CPUのクロックアップが可能で、かなりの高速化が可能になります。
sentaro様が開発された Ftune 2 と言うアドインを、私は使っていて、高速動作をしたい時は、ノーマルの 29MHz程度から一気に 236 MHz のオーバークロック動作ができます。その差は歴然です(上記の2つの移植記事を参照)。

 ⇒ Ftune 2: fx-9860GII のオーバークロック・アドイン、他の機種への対応バージョンもあります。


プログラムの動作速度だけが評価基準ではありません。作ったプログラムの使いやすさを考えますと、チョット話しが違ってきます。

私自身が 必要に迫られて、そしてあったら便利だと思って、複数のプログラムを作って、ほぼ毎日使っています。 fx-5800P では [FILE] キーを押せば、プログラムリストが出てきます。最大5つのプログラムをリストのトップに表示させることもできます。日常使いのプログラムは、このトップ5に入っています。

電源ON [FILE] キー [▼] キー数回

これで、プログラムを呼び出して実行できます。
トップ5にないプログラムを探す際には、プログラムリストが表示されている時は、自動的にアルファベット入力モードになっているので、プログラム名の頭のアルファベットのキーを押すだけで、近い名前のプログラムが呼び出されます。非常によく考えられています。

残念ながら、fx-9860GII では、このようなことが出来ません。

このプログラム呼び出しの迅速性、関数電卓としての操作性、そして携帯性の良さから、私は fx-5800P を日常使いから外すことはないと思います。fx-9860GII が日常使いになるには、何か新しい事情が必要でしょう。

まだ、グラフ機能や作表機能を試していません。プログラムからグラフ機能を使うことも出来ますので、このあたりに fx-9860GII の下克上の可能性はありそうです。


最近の価格

Casio fx-9860GII は、グラフ関数電卓と言われるジャンルの製品で、電卓製品のなかでは最も高機能なものです。その分販売価格も高くなっています。日本では、アメリカの2倍近い価格設定なので、日本国内で入手しようという気は全くありません。

先週末 Amazon で並行輸入品が ¥9,000 でありました。本日見ると ¥8,980 と、ついに8,000円台に突入しました。
fx-5800P が Amazon で¥6,261 なので、fx-9860GII は買い時になったと思われます。

[2014/12/20 追記] 
昨日 Amazon を見てみると、fx-9860GII 並行輸入品が ¥8,500 とさらに値下げされていました。年末セールなのかも知れませんが、どこまで下がるのか楽しみです。ちなみに fx-5800P は¥6,235 になっていて、これも値下げが進んでいます。
恐らく、今の年末セールから3~4月の新学期シーズンまでが安値が期待できるように思います。


製品保証?

上記の価格は並行輸入品のものですから、製品保証の問題がグレーゾーン。保証書の紙は製品に添付されていますが、販売店のスタンプが押されていません。購入店のある国内でのみ保証有効、との注意書きの紙も添付されていました。私はアマゾンで購入しましたが、それは日本国かどうかがグレーです。国内で対応してくれるかは分かりません。




 


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

人気ブログランキングへ


FC2ブログランキングへ

 


keywords: fx-5800P、fx-9860GIICasioBasic、プログラム関数電卓

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


関連記事

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

fx-9860GII への移植 - 素因数分解

2014/12/13: 修正
2015/02/28: 追記

これまで、fx-5800P の Casio Basic で素因数分解のプログラムを紹介してきたが、これを fx-9860GII へ移植してみました。

今回のプログラム移植にあたっては、fx-5800P にある 配列変数 Z[ ] が fx-9860GII には無いので、これをどうするか、が主なテーマです。今回は、配列変数の代わりに行列を用いることにします。

なお、出力命令 ◢ を使った時の動作が、fx-5800P と fx-9860GII では異なることは、ピタゴラス数探索プログラムの fx-9860GII への移植 で経験しています。⇒ こちらの記事

これは、本来表示される筈の行が上書きされて - Disp - と表示されてしまう問題です。今のところ、決定的な解決策がまだ見つかっていないので、表示全体を1行下に下げると言う方法で回避することにします。



配列変数を行列に置き換える

配列変数 Z[N] は、1行N列の行列と同じなので、以下のようにします。

1. 領域確保 (要素20個を確保して、各要素を 0 で初期化する)
  ・配列変数の確保: 20→DimZ
   の代わりに
  ・1行20列の行列確保: {1,20}→Dim Mat Z
   [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]→Mat Z これでも間違いないが、効率が悪い。
   fx-9860GII の Casio Basic では 最大999行999列の行列まで使えるので、Dim コマンドを用いるべき。

   [2014/12/08 sentaro様のご指摘により記述を修正]

2. 使い方
  ・ 配列変数: Z[K]
   の代わりに
  ・行列 Z : Mat Z[1,K]

3. 領域解放
  ・配列変数の解放: 0→DimZ
   の代わりに
  ・行列 Z の解放: ClrMat Z

要するに、プログラムの記述を、上のように置き換えれば動作するはずです。



- Disp - 表示による問題の回避

Locate コマンドで指定する座標を 下に1つ増やす (Y座標を1つ増やす) ことで対応します。
今回は、多くの Locate コマンドの座標指定に変数や式を用いているので、チョット注意が必要です。但し、今回のプログラムで使っているLocate コマンドのY座標は、変数 L やLを使った式で指定しているので、L の値を1つ増やすように変更すれば良さそうです。具体的には、一番下に示すプログラムを見てください。



全画面消去コマンドの変更

fx-5800P の全画面消去は Cls コマンドを使用します。テキスト表示の全消去機能です。
一方、fx-9860GII は、テキスト表示とグラフィック表示の両方の機能があり、テキスト表示の全消去は ClrText コマンドを使います。
ちなみに、グラフィック表示の全消去は ClrGraph コマンドです。


今回は、配列の扱い、出力命令の動作と画面行数に合わせたLocateコマンド引数の修正のみで、fx-9860GII に移植したプログラムは問題なく動作しました。要所を分かっていれば、Casio Basic は移植性が高いと言えます。



プログラム実行画面

fx-5800P と fx-9860GII の両方で、ほぼ同じ Casio Basic プログラムを走らせた時の、画面表示の比較です。


※プログラムを起動した時の画面:

PD_5800P_1 PD_9860GII_1 


※数を入力する:

PD_5800P_2 PD_9860GII_2  


※素因数分解を最後まで計算したあとで、結果を表示:

PD_5800P_3 PD_9860GII_3  

1行表示されたら [EXE] キーを押して次の行を表示させます。
これを繰り返して、上のように が表示されたらそれが最後の素因数です。
ここで、 [EXE] キーを押せば最初の入力画面に戻ります。

fx-5800P では4行を超えると再び1行目から上書きします。
fx-9860GII では7行を超えると再び行目から上書きします。



計算速度の比較

fx-9860GII は、ノーマル (約29MHz) と オーバークロック (約236MHz) で測定しました。

入力した自然数結果fx-5800Pfx-9860GII (29MHz)fx-9860GII (236MHz)
123453 x 5 x 8232.2秒0.5秒 (4.4倍)計測不能 (一瞬)
12345626 x 3 x 6432.6秒0.6秒 (4.3倍)計測不能 (一瞬)
1234567127 x 97216.5秒1.5秒 (4.3倍)0.3秒
123456782 x 32 x 47 x 145936.6秒1.5秒 (4.3倍)0.4秒
12345678932 x 3607 x 38032分43秒33秒 (4.9倍)7.2秒
98765432132 x 172 x 37972128秒6秒 (4.7倍)1.3秒
9876543223 x 37 x 33366727秒5.5秒 (4.9倍)1.3秒
98765433 x 227 x 1450311秒2.4秒 (4.6倍)0.6秒
9876542 x 3 x 97 x 16975秒1.3秒 (3.8倍)0.4秒
987655 x 197537秒1.6秒 4.3倍)0.3秒
987622 x 3 x 8233秒0.7秒 (4.3倍)計測不能 (一瞬)

今回の速度比較には、表示速度は含まれず、プログラムの実行速度の差が反映されていると考えられます。

※ オーバークロックは、sentaro様作のアドイン Ftune 2 を使用しています。Ftune 2 については、こちら を参照のこと。




プログラムの比較

左が fx-5800P 用プログラム、その右に fx-9860GII 用に変更したプログラムを並べ、変更箇所を赤文字で示しています。

[2015/02/28 追記]
※ fx-9860GII へ転送して使えるプログラムファイル prime.g1m のダウンロード

素因数分解_改造版ソース PD2_9860GII_src 



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

人気ブログランキングへ


FC2ブログランキングへ


 

keywords: fx-5800P、fx-9860GII素因数分解、プログラム関数電卓

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


関連記事

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

fx-9860GII への移植 - ピタゴラス数

2014年12月06日
2014/12/07: fx-9860GII オーバークロックでのテストを追加
2014年12月14日: 配列変数の代わりには行列が良い点を追記

fx-9860GII を入手したので、さっそくピタゴラス数探索プログラムを fx-5800P から移植してみました。
 ⇒ fx-5800P でピタゴラス数

このプログラムについて、fx-5800P のプログラムとの違いは、以下を考慮すれば良いだけの筈です。

・キーコード: Getkey が返す値が 全く異なる
・Locate コマンドの引数: 画面が 21 x 7 と広い

ところで、キーコードを調べるプログラム GET KEYCODE (プログラムライブラリ - キーコード取得 参照) は、そのまま100% 互換で移植できます。fx-9860GII はプログラム名を8文字以内で指定しなければならないので、fx-9860GII のプログラム名を KEYCODE としました。
 ⇒ プログラムライブラリ - キーコード取得

具体的な比較は上記参照。これでキーコードを調べると、[EXE] キーは 31、[(-)] キーは 41 でした。


さて、fx-5800P用のピタゴラス数探索プログラムで、キーコードのみを変更してfx-9860GII で走らせてみると、画面の1行目に

- Disp -

と表示されてしまい、1行目の表示に上書きされていまうことが分かったので、Locate の引数を変更して、表示全体を1行下にずらすようにしました。

表示行を1行下にずらした - ステップモード

9860_Pytha1 


表示を1行下にずらした - 連続モード

9860_Pytha2 


fx-9860GIIピタゴラス数探索プログラム: PYTHA
3→M:1→N:1→D:1→D:1→E     (初期化処理)
Locate 1,3,"A="            
(初期画面表示)
Locate 1,4,"B="
Locate 1,5,"C="

Lbl 0

E=0⇒Locate 14,2,"(-):Stop"
(M2-N2)÷2→A             
(ピタゴラス数の計算)
MN→B
(M2+N2)÷2→C

Locate 1,1,D              (見つかった回数の表示)
Locate 3,2,"          "    (スペース19個)
Locate 3,2,A              
(ピタゴラス数の表示)
Locate 3,3,"          "    (スペース19個)
Locate 3,3,B              (ピタゴラス数の表示)
Locate 3,4,"          "    (スペース19個)
Locate 3,4,C              (ピタゴラス数の表示)

Getkey=41⇒1→E
0→K
While Getkey=31
Isz K:K=20⇒Break
WhileEnd:K=20⇒0→E

Locate 14,2,"EXE:Next"◢    
(操作法表示&プログラム一時停止)

Do                     
(次の M と N を探す)
N-2→N
If N<0:Then
M+2→M:M-2→N
IfEnd
N=1⇒Break
LpWhile Frac(M÷N)=0
Isz D                    
(見つかった回数を1つ増やす)

Goto 0



fx-9860GII は fx-5800P よりもかなり動作が速いようで、[EXE] キー長押しの時間を長く設定しないと長押しにならないことから、fx-5800P で長押し時間のカウンタ 7 だったのを、20 に変更しました。

ピタゴラス数100個を探索する時間を比較してみると

・ fx-5800P:                 40秒
・ fx-9860GII (ノーマル 29MHz):       18秒
・ fx-9860GII (オーバークロック 236MHz):  4秒  [2014/12/07 追記]

と、sentaro様のご報告と同様に、fx-9860GII (ノーマル) は約2倍の速さでした。

[2014/12/07 追記]
ちなみに、sentaro様作アドイン Ftune 2 によるオーバークロックで 約236MHz にすると、上記の通り fx-5800P の10倍の速度となりました。

Ftune 2 は、
こちら
このアドインを起動後、メモリーチェックを行い、F5 キーで上記設定ができました。

なお、オーバークロックに合わせて、長押し検出のカウンタは 150 にしています(そうでないと速すぎてステップモードに切り替えが難しい)。



実際見た目も速くなっています。

ノーマル (29MHz)




オーバークロック (236MHz)



これは、凄い速さですね!



fx-9860GII は、並行輸入品 (¥9,000) なので、マニュアル類に日本語はありません。ところが、添付CDに、日本語のマニュアルがありました。但し、fx-5800P と同様、プログラミングに関しては殆ど役に立たない、最低限の内容しか記載がありません。

そこで、開封し、電池を入れて、マニュアルなしでいきなり キーコード取得プログラムを入力してみました。
たった20行のプログラムですが、コマンドをどこから選んで良いのか、最初はサッパリ分からず、結構な時間をかけて入力完了!
これで、大雑把に、どこにどのコマンドがあるのかが分かりました。

このプログラムは、手直し無しで正常動作しました。fx-5800P から fx-9860GII への互換性がかなり高いことが証明されました。

次にピタゴラス数探索プログラムの入力は、かなり楽になりましたが、ここで - Disp - 表示という思わぬ罠がありました。
この表示は、出力命令 ◢ を使うと、現れるようです。

例えば、1行だけのプログラム

Locate 1,1 "1ST LINE"

を実行すると、1行目の左端から、

1ST LINE

と表示されますが、出力命令 ◢ を使って、

Locate 1,1,"1ST LINE"◢

として、実行してみると、1行目の右端に

- Disp -

と表示され、1ST LINE が表示されません。

- Disp - が表示されるとき、その行全体を左端から上書きして表示されているために、1ST LINE が消えているようです。

次に、

""
""
""
""
""
""
Locate 1,1,"1ST LINE"◢


を実行してみると、"" で内部カーソルが6回改行され、7行目に - Disp - が表示されるので、1行目の 1ST LINE は上書きされずに、きちんと表示されます。

このことから、- Disp - は現在の内部カーソルの位置を示していると思われます。

Locate 1,1,"1ST LINE"◢

が正常に表示されない問題を避ける方法がないものか、もう少し調べて見ようと思います。


他にも、色々と触っていて気付いたのですが、fx-9860GII には配列変数がありません。その代わりに List コマンドを使うしかないのかなぁ、と思いますが、その処理速度がどの程度か、いずれ調べてみようと思います。

[2014年12月13日 追記]
fx-9860GII (ノーマルクロック: 約29MHz) でリストと行列のアクセス速度を測定したところ、行列の方が速いことが分かりました。速度と汎用性を考えると、fx-5800P の配列変数の代わりに fx-9860GII で行列を使うのが正解です。

処理内容処理時間 (ミリ秒)
リスト読み出し13.2
リスト書き込み17.6
行列読み出し10.7
行列書き込み12.0
※ 測定はココ の方法に準じて実施。但しループ回数は2000回とした。


fx-9860GII は標準で 29MHz程度。クロックが8倍速くなっているのに、表示まで含めた速度は4.5倍程度にとどまっている、という上記の結果から、表示(描画)速度がかなり遅くて、これが全体の速度を決めてしまう(律速)ことになっているようです。

fx-5800P が14MHzも無いとするならば、fx-5800P の描画速度がfx-9860GII に比べて速いと言えます。




fx-9860GII 用ピタゴラス数探索プログラム: PYTHA

※ fx-9860GII へ転送して使える プログラムファイル pytha.g1m のダウンロード

fx-9860GII PYTHA_src 
 ※ 13行目、15行目、17行目の Locateコマンドの空白はスペース19個




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

人気ブログランキングへ


FC2ブログランキングへ

 

keywords: プログラム関数電卓、fx-5800P、fx-9860GII、キー長押し、CasioBasic、 ピタゴラス数

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

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

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

やす (Krtyski)

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


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

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

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


人気ブログランキングへ


FC2ブログランキングへ


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

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

この人とブロともになる

QRコード
QR