Casio Basic入門53

Casio Basic入門
<目次>

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

追記修正 2016/07/17

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

Chapter 9 - 初級

前回: Casio Basic入門52 を見る


◆ Chapter 9 の目標: 簡単な換算プログラム - 入力ボックスの活用


Chapter 9-3 
fx-5800P での3桁区切り表示を高速化する

前回、3桁区切りできる複利計算プログラムを再掲します。

・サブルーチン: 3DIGIT
・メインルーチン: COMPINT2

ファイル名: 3DIGIT

Z=0⇒Retuen
Int(log(Z))+1→D
D-3Int(D÷3)→F

For 1→I To D
Int(Z÷10^(D-I))→C
Locate X+I-1,Y,C
Z-C10^(D-I)→Z
If I-3Int(I÷3)=F
Then Isz X
I<D⇒Locate X+I-1,Y,","
IfEnd
Next



ファイル名: COMPINT2
Locate 1,1,"1-C:"
Locate 1,2,"2-R:"
Locate 10,2,"3-Y:"
Locate 1,3,"TOTAL"
Locate 1,4,"MONTH"


0→B:0→R:0→N:0→T:0→M

Do

0→K:Do
Getkey→K
LpWhile K=0
K=73⇒Break

If K=35
Then
5→X:1→Y:8→D:1→E
Locate X,Y,"      " (スペース11個)
Prog "INP":Z→B
Prog "3DIGIT"
Else If K=36
Then
5→X:2→Y:4→D:1→E
Prog "INP":Z→R
Else If K=37
Then
14→X:2→Y:3→D:1→E
Prog "INP":Z→N
IfEnd:IfEnd
IfEnd

If BRN:Then
Int(B(1+R÷100)^(N))→T
Locate 7,3,"     " (スペース10個)
T→Z:7→X:3→Y
Prog "3DIGIT"
Int(T÷N÷12)→M
Locate 7,4,"     " (スペース10個)
M→Z:7→X:4→Y
Prog "3DIGIT"

IfEnd

LpWhile
 1
Cls
Locate 7,2,"BYE!"





前回のプログラムと高速化の試み

以下のように、3桁区切りで表示ができましたが、

8digit_input 

左から右へ、パラパラと表示されて時間がかかります。

今回のプログラムで一番動作時間がかかるのは、Locate コマンドです。そして、For ループで Locate が何度も実行されているので、表示に時間がかかると考えています。このプログラムでは、例えば 12345678 を表示するには Locate を10回実行しています。

そこで、表示を高速化するには、Locate が実行される回数を減らせば良いことになります。

私が最初に考えたのは、例えば 1234567812,345,678 として表示するために Locate を使って、

1) 12 を表示
2) ,(コンマ)を表示
3) 345 を表示
4) ,(コンマ)を表示
5) 678 を表示


つまり、Locate 実行の回数が10回から5回へ半減しますので、良さそうです。実際に作ってみると、問題がありました。

それは、例えば 139096 を3桁区切りにすると 139,096 となるべきところ、そうはならないバグです。このバグはコーデイングのバグではなくて、fx-5800P Casio Basic の限定的な機能が関係した本質的な問題でした。

上の考え方だと

1) 139 を表示⇒問題なし
2) ,(コンマ)を表示⇒問題なし
3) 096 を表示⇒
問題発生


Locate コマンドで 数値 096 を表示すると 96 になってしまいます。
つまり、3桁区切りの表示が 139,96 と妙なことになります。

fx-5800P Casio Basic では文字列を扱うコマンドが無いので、096 を一旦文字列に変換して Locate で表示することができません。
ただし、この問題は簡単に解決できます。096 は、3桁でなくて2桁なので、3桁未満の時は文字 "0" を先に表示してから3桁未満の数値を表示すれば良いだけです。

あるいは、先に文字列 "000" を表示した上に 必要な桁から2桁か2桁の数値を上書きする方法もあります。 
過去の Casio Basic 入門でも、この方法は使っています。

但しこれらの方法では、ある所定の数値の場合に Locate の実行回数を減らすことができずい、本質的な解決策とはならない中途半端な方法だと考えました。

そんなわけで、表示に時間がかかるものの、ロジックとしては素直でコンパクトな前回のプログラムを紹介したわけです。




3桁表示の高速化

sentaro 様から面白いロジックをご提案頂き、それを紹介したいと思います。これは、3桁区切りをチョット巧妙に実現するものです。そのロジックやプログラムの実装方法は初級というよりも中級に入るかも知れません。

例えば 12345678 を表示する前に、コンマが入るところに 0 を入れた数値を作って、

1203450678

として、一旦この数値を Locate で表示します。

次に、コンマが入るところの 0,(コンマ)で上書きして(Locate コマンド使用)、

12,345,678

とすれば良い...といった考え方です。私には思いつかなかった面白いものです。

この8桁の数値を3桁区切り表示する時の Locate 実行回数は3回になって、激減します(前回のプログラムだと10回実行)。

このロジックだと、上で問題が発生した 139096 の場合は、一旦 1390096 に変換して、この数値を Locate で表示。続いてコンマが入るべき 0 の位置に Locate, (コンマ)を上書きするので、

139,096

と正しく表示されます。

なかなかよく考えられたロジックですね。

前回作ったプログラムでは、Locate を7回実行するところ、2回で済むので、表示が大いに高速化されます。




新ロジックの実装

そこで、3桁区切り表示を行うサブルーチン 3DIGIT3DIGIT2 とします。
メインルーチンは、COMPINT2COMPINT3 にします。


プログラムを以下に示します。

・サブルーチン: 3DIGIT2
・メインルーチン: COMPINT3

ファイル名: 3DIGIT2

Z=0⇒Retuen
Int(log(Z))+1→K
(K≥4)+(K≥7)+(K≥10)→I
Frac(Z÷1
x103)×1x103→U
Int(Frac(Z÷1x106)×1x103)→V
Int(Frac(Z÷1x109)×1x103)→W
Int(Z÷1x109)→D

If L≤8:Than
Locate X,Y,1x108×W+1x104×V+U
I≥1⇒Locate X+K-2-(I=1),Y,","
I≥2⇒Locate X+K-6,Y,","
Else
Locate X+3+2×(I≥3),Y,1x107+1x104×V+W
Locate X+0,Y,1x104×D+W
Locate X+K-2+(I≥3),Y,","
Locate X+K-6+(I≥3),Y,","
I≥3⇒Locate X+1,Y,","
IfEnd



変数の説明

入力値: Z
X座標: X
Y座標: Y


ワーク変数 U:下3桁
ワーク変数 V:中3桁
ワーク変数 W:上3桁
ワーク変数 D:最上位1桁
ワーク変数 K数値の桁数
ワーク変数 I:三桁区切り文字の数



ここで、解説を2つだけ...


青文字の( ) の部分

この ( ) は、0か1かの値になります。( ) の中が正しいなら(真ならば)1、正しくなければ(偽ならば)0になります。この性質をうまく使って計算式に中で利用しています。


赤文字 x104 の表記

これは [x10x] キーを押して入力します。


メインルーチンは、呼び出すサブルーチン名を変更するだけ...

ファイル名: COMPINT3
Locate 1,1,"1-C:"
Locate 1,2,"2-R:"
Locate 10,2,"3-Y:"
Locate 1,3,"TOTAL"
Locate 1,4,"MONTH"


0→B:0→R:0→N:0→T:0→M

Do

0→K:Do
Getkey→K
LpWhile K=0
K=73⇒Break

If K=35
Then
5→X:1→Y:8→D:1→E
Locate X,Y,"      " (スペース11個)
Prog "INP":Z→B
Prog "3DIGIT2"
Else If K=36
Then
5→X:2→Y:4→D:1→E
Prog "INP":Z→R
Else If K=37
Then
14→X:2→Y:3→D:1→E
Prog "INP":Z→N
IfEnd:IfEnd
IfEnd

If BRN:Then
Int(B(1+R÷100)^(N))→T
Locate 7,3,"     " (スペース10個)
T→Z:7→X:3→Y
Prog "3DIGIT2"
Int(T÷N÷12)→M
Locate 7,4,"     " (スペース10個)
M→Z:7→X:4→Y
Prog "3DIGIT2"
IfEnd

LpWhile
 1
Cls
Locate 7,2,"BYE!"



3桁区切りでの表示が劇的に速くなりました。
コードを眺めて、プログラムの巧妙さを楽しんでください。



fx-5800P の Casio Basic には文字列処理の機能がありませんが、工夫次第で色々と実現できるわけで、逆に言えば Casio Basic がそれだけ高機能だとも言えますね。



つづく...

Casio Basic入門54Casio Basic入門G01 / 目次




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

人気ブログランキングへ


FC2ブログランキングへ



 



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

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




関連記事

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

コメントの投稿

非公開コメント

fx-5800でも十分いけますね(^^)

管理人様、こんにちは!

数値をまとめて処理は若干トリッキーではありますが(^^;取り上げていただきましてありがとうございます。

今回の例だとLocateの使用回数を減らすことが実行速度に直結していることがよくわかりますが、fx-5800pでも表示機構はfx-9860GIIと同様に表示コマンド毎に画面全体のLCD転送が発生しているものと推測されるので、やはり表示は最小限に抑えることが高速化のポイントになってきますね。

管理人様の一桁づつ表示は目に見える逐次処理感がプログラム的に素直でよいですし、表示のまったり感が初期の液晶電卓のような趣があって懐かしさも感じます(^^)

そして何より文字列処理の無いfx-5800Pでも3桁区切り表示が出来てしまうことがCasioBasicの優秀さを表してますね!

3DIGIT2を12桁まで対応版です。

管理人様、こんにちは!

3DIGIT2では10桁を超えると表示がおかしくなるので(^^;
fx-5800Pで表示可能な12桁まで対応してみました。

3DIGIT2をベースに改造です。
乗算省略形式にして、JをX桁計算のワーク変数として追加使用しています。
--------------------------------------
'ProgramMode:RUN
Int log Z+1->K
(K>=4)+(K>=7)+(K>=10)->I
Exp3Frac (Z/Exp3)->U
Int (Exp3Frac (Z/Exp6)->V
Int (Exp3Frac (Z/Exp9)->W
Int (Z/Exp9)->D

If K<=8:Then
Locate X,Y,Exp8W+Exp4V+U
I>=1=>Locate X+K-2-(I=1),Y,","
I>=2=>Locate X+K-6,Y,","
Else
X+K-6+(I>=3)->J
Locate J,Y,Exp7+Exp4V+U
Locate X,Y,Exp4D+W
Locate J+4,Y,","
Locate J,Y,","
I>=3=>Locate X+K-9,Y,","
IfEnd
--------------------------------------
(CG10/20、C.Basic、さらにFD10Proでそのまま使えると思われるテキスト形式です)

Re: 3DIGIT2を12桁まで対応版です。

sentaro様

桁オーバーフロー対応ですね。

最初のパラパラ表示版では、ここは使い方で対応してもらうようにして、きちんとやっていません。

せっかくなので、sentaro様の高速版とパラパラ版の両方で、表示桁管理を新しいネタとして追加してみようかな、と思います。

こうやって、話題が膨らむと楽しいですね(^_^)/

ありがとうございます。

文字列を使ってみました。

管理人様、こんにちは!

>最初のパラパラ表示版では、ここは使い方で対応してもらうようにして、きちんとやっていません。

じつは、管理人様のパラパラ表示版(ネーミングにちょっとウケました!(^^;)だと11桁以上になっても問題なく表示可能!なので12桁まで対応に修正させていただいた次第です(^^;


>せっかくなので、sentaro様の高速版とパラパラ版の両方で、表示桁管理を新しいネタとして追加してみようかな、と思います。

さらに追加ネタ?といっては何ですけど、fx-9860GIIでは文字列が使えるので、パラパラ表示版を文字列版に改造してみました。
Locateが最後の一回だけになったので、表示が遅く内部演算が速いCG10/20では高速版とあまり変わらない表示速度になる感じです。
--------------------------------------
Z->A
Int (log A)+1->D
D-3Int (D/3)->F

""->Str 1
For 1->I To D
Int (A/(10)(D-I))->C
Str 1+StrMid("0123456789",C+1,1)->Str 1
A-C(10)(D-I)->A
If I-3Int (I/3)=F
Then
I<D=>Str 1+","->Str 1
IfEnd
Next
Locate X,Y,Str 1
--------------------------------------
(CG10/20、C.Basic、さらにFD10Proでそのまま使えると思われるテキスト形式です)


>こうやって、話題が膨らむと楽しいですね(^_^)/

はい!
身近なところにプログラムのネタは転がっているということですね(^^)
最新記事
最新コメント
カテゴリ
C# (3)
検索フォーム
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

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


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

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

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


人気ブログランキングへ


FC2ブログランキングへ


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

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

この人とブロともになる

QRコード
QR