Casio Basic入門55
Casio Basic入門
誤字脱字・記載ミスや分かりにくい表現は随時追記・修正します
2017/11/03
訂正 2017/11/04
2017/11/03
訂正 2017/11/04
4. CasioBasicを使ってみる(続き)
前回: Casio Basic入門54 を見る
Chapter 10 - 中級
◆ Chapter 10 の目標: 3桁区切り出力 - 汎用サブルーチンの作成
大きな数が出力された時、例えば、
59265358
だと数の大きさがよく分からないのですが、
59,265,358
だと、5千9百万くらいとスグに分かります。
Casio Basic が使えるプログラム電卓には3桁区切り出力の機能がありません。そこで Casio Basic で作るプログラムで、
Locate X,Y,Z
の代わりに、
Prog "3DS"
と記述すると3桁区切り出力できるサブルーチン 3DS を作ります。3DS は少し機能追加してより一般的に使える汎用サブルーチンとして仕上げます。
前回 (Chapter 9) の後半で、sentaro様ご提案の高速出力する3桁区切りサブルーチンを取り上げ、さらっと紹介しています。これは非常によく考えられたロジックなので、今回はこのプログラムを掘り下げた上で、fx-5800P用汎用サブルーチンとして仕上げ、グラフ関数電卓用に拡張します。
- fx-5800P用高速3桁区切りサブルーチンの詳細を紹介
- 機能追加を必要最低限の改造で行って fx-5800P用の12桁対応・汎用サブルーチンとしてまとめる
- グラフ関数電卓用に移植し、15桁対応に機能拡張
▋3桁区切り出力サブルーチンの使い方
サブルーチンのプログラム名は、短い方が入力が楽で、3-Digit Separator (3桁区切り) から 3DS としました。
Locate X,Y,Z の代わりに Prog "3DS" と書いて3桁区切りを実現します。但し Locate コマンドでは、X, Y Z の3つのパラメータを渡せますが、サブルーチン 3DS にはパラメータが渡せません。そこで、Prog "3DS" 実行の直前に、変数 X, Y, Z を設定します。
Casio Basic の特性として、メモリ内にある全てのプログラムで変数が共有され、全ての変数は "大域変数 (グローバル変数)" となっています。そこで、3DS を実行する直前に X, Y, Z に値を格納し、それを 3DS で利用します。
・変数 X は、3桁区切り出力を開始する桁、Locate X,Y,Z の X と同じ
・変数 Y は、3桁区切り出力を開始する行、Locate X,Y Z の Y と同じ
・変数 Z は、3桁区切り出力する整数、Locate X,Y,Z の Z と同じ
例えば、123456789012 を 2桁3行から3桁区切り出力するために、
2→X:3→Y:123456789012→Z
Prog "3DS"
と書けば、2桁3行目から 123,456,789,012 と出力します。
或いは、予め 123456789012 が変数 A に格納されていると、
2→X:3→Y:A→Z
Prog "3DS"
と記述すると、同じ出力になります。
▍使用上の注意点
3DS では、X, Y, Z に加えて、以下の変数を使っています。
Z: 3桁区切りする数値
X: 出力する桁
Y: 出力する行
-----
K: 数値の桁数
I: 区切り文字","の数
U: 最下位3桁の数値
V: 4~6桁の3桁の数値
W: 7~9桁の3桁の数値
D: 10桁目以上の数値
J: 9桁目区切り文字位置
3DS が走ると Y, Z 以外の上記の変数の値が変化します。メインルーチンでこれらの変数を使う時は、3DS で値が変わっても問題無いように使います。一番簡単な方法は、メインルーチンで上記変数名を使わないことです。
既に作ってあるプログラムに3桁区切り出力機能を追加する場合 (私自身はこのケースが多い) は、メインルーチンの中で上記と同じ変数名を別の変数名に変えるのが確実です。同じ変数名を多く使ったメインルーチンで3桁区切り出力機能を追加するときは、メインルーチンをよく調べて、変数の値を保持させたい有効範囲の外で 3DS を使う場合は、同じ変数を使っても問題ありません。
処理速度が多少遅くなりますが、殆どのプログラムで使える万能な方法もあります。配列変数 (fx-5800P) や行列 (グラフ関数電卓) を使って、3DS を使う前に上記の変数 (Y, Z 以外)とかち合うメインルーチンの変数を一旦配列変数 (行列) にコピー (待避) し、3DS 使用後に 配列変数 (行列) から元の変数へコピー (復帰) します。この方法は柔軟に使える反面、配列変数 (行列) は処理が遅いので、特に高速動作が必要なプログラムに限っては、あまり良い方法ではありません。
以上の方法をうまく組み合わせると、既存のプログラムで数値を出力するときに3桁区切りが実現できます。
前回さらっと紹介した高速版3桁区切り出力サブルーチンについて、詳細をみてゆきます。
Chapter 10-1
高速版3桁区切り出力サブルーチンの特長
高速表示版は、12行+α の簡潔なプログラムですが、幾つかの大きな特長があります。
[ロジック]
Locate コマンドの使用回数を大幅に抑えることで、高速出力を実現しています。
例えば12桁の数 123456789012 を3桁区切り出力するとします。
- 最初に、下から3桁づつ 012 と 789 と 456 を切り出し、残りの桁 123 も切り出します。
- 次に、1x107 + 789x104 + 012 = 17890012 を算出。3桁の数の間に 0 を挟み込んだところがミソ!
- さらに、123x104 + 456 = 1230456 を算出。ここでも3桁の数の間に 0 を挟み込んでいる。
- 2回の Locate コマンドで表示位置をずらして、これら2つの数が繋がるように出力 ⇒ 123045617890012
- ここで、Locate 一回で出力するのは8桁以下なので、指数表示にならないのも重要なポイント!
- つなぎの 0 や 1 の位置に Locate コマンド3回で区切り文字 "," を1つづつ出力 ⇒ 123,456,789,012 となる
[特長1]:Locate 使用回数を減らして高速化
区切り文字が入る位置に予め 0 や 1 で繋いで数値を出力し、あとでつなぎの 0 や 1 の位置に区切り文字を上書きすることで、Locate 使用回数を減らしています。
[特長2]:指数表示を抑える
上の一連の処理で、実際の1回の計算で算出された数の最大のものは、1x107 (8桁) である点が重要です。Casio Basic が走るCasioの電卓では、出力する数の桁数が11桁以上になると強制的に指数表示になる仕様で、指数表示になってしまうと区切り文字の付けようがありません。Locate で出力する数は必ず10桁以下にする必要があります。
[特長3]:本来指数表示になる11桁以上の3桁区切りが可能
一回の Locate コマンドでの出力を10桁以下の数に限定し、11桁より上位の桁は、出力位置をずらして再度 Locate で繋がるように出力するロジックを採用することで、11桁以上の出力桁数に柔軟に対応できるのも特長です。
具体的にコードを理解してゆきます。
ここで使っている関数は、Int(、Frac(、log(、x10 です。
ここで 1x106 は "1かける10の6乗" (=1,000,000) です。
高速版3桁区切り 3DS | |||
Z=0⇒Return | ⇒ | Zがゼロの時は何もしないでメインルーチンに戻る | |
Int(log(Z))+1→K | ⇒ | Z に格納された数の桁数を求める (K) | |
(K≥4)+(K≥7)+(K≥10)→I | ⇒ | 必要な区切り文字の数を求める (I)。論理演算式は、真なら1,偽なら0の値を持つ特性を利用し、( ) の中は0か1なので、この式で区切り文字の数が算出できる。 | |
If X+K+I>17 Then Locate X,Y,Z Return:IfEnd | ⇒ | 出力開始桁 (X) と桁数 (K) と 区切り文字数 (I) の和は出力結果の右端の桁。この和が17 を超える時は、1行から溢れて区切り文字出力が正しくできない。この場合は、単純に元の数 Z を区切り文字無しで出力する。 | |
1X103Frac(Z÷1X103)→U Int(1X103Frac(Z÷1X106))→V Int(1X103Frac(Z÷1X109))→W Int(Z÷1X109)→D | ⇒ | 下位から3桁づつ切り取る。一番下位の3桁が U、次が V、Wと続く。D は10桁目より上位の数で3桁とは限らない (4桁以上のケースもある)。 | |
If K≤8:Then Locate X,Y,1X108W+1X104V+U I≥1⇒Locate X+K-2-(I=1),Y,"," I≥2⇒Locate X+K-6,Y,"," | ⇒ | 桁数が8以下の時は、区切り文字の位置に 0 を挟んだ数を作るために 最上位2桁(W)を一旦 x108 倍する処理がある。2桁の x108 倍は10桁になるが、一気に10桁の数を Locate で出力しても指数表示にはならない。そこで 桁数が8以下の時の Locate を3回用いる軽い処理をここに記述する。 | |
Else Locate X+K-6+(I≥3),Y, 1X107+1X104V+U Locate X,Y,1X104D+W Locate X+K-2+(I≥3),Y,"," Locate X+K-6+(I≥3),Y,"," I≥3⇒Locate X+K-9,Y,"," IfEnd | ⇒ | 桁数が9桁以上の場合の処理。具体的には冒頭に示した処理。 このロジックでは最大12桁対応になっている。Locate を5回用いており、依然として軽快に動作する。 | |
ここまでが、前回、Chapter 9 で紹介した 高速版3桁区切り出力サブルーチンの詳細です。
汎用性のあるサブルーチンとしては、上の 3DS には少し問題があります。そこで次回は、評価用プログラムを作って、実際の動作を調べ、改善を行います。
つづく...
⇒ Casio Basic入門56 / Casio Basic入門G01 / 目次
応援クリックをお願いします。励みになるので...
keywords: fx-5800P、CasioBasic、入力ボックス, プログラミング入門、プログラム関数電卓
リンク集 | ブログ内マップ
- 関連記事
-
- Casio Basic入門57 2017/11/05
- Casio Basic入門56 2017/11/05
- Casio Basic入門55 2017/11/04
- Casio Basic入門54 2017/11/03
- Casio Basic入門53 2017/10/25