e-Gadget - プログラム関数電卓 Casio Basic入門55

Casio Basic入門55

Casio Basic入門
<目次>

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

 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,ZX と同じ
・変数 Y は、3桁区切り出力を開始する行、Locate X,Y ZY と同じ
・変数 Z は、3桁区切り出力する整数、Locate X,Y,ZZ と同じ

例えば、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桁区切り出力するとします。
  1. 最初に、下から3桁づつ 012789456 を切り出し、残りの桁 123 も切り出します。
  2. 次に、1x107 + 789x104 + 012 = 17890012 を算出。3桁の数の間に 0 を挟み込んだところがミソ!
  3. さらに、123x104 + 456 = 1230456 を算出。ここでも3桁の数の間に 0  を挟み込んでいる。
  4. 2回の Locate コマンドで表示位置をずらして、これら2つの数が繋がるように出力 ⇒ 123045617890012 
  5. ここで、Locate 一回で出力するのは8桁以下なので、指数表示にならないのも重要なポイント!
  6. つなぎの 01 の位置に 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、次が VWと続く。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 / 目次



応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ






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

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


関連記事

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

コメントの投稿

非公開コメント

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

やす (Krtyski)

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


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

プログラム電卓を実際に使って気づいたこと、自作プログラム、電卓での Casio Basic, C.Basic そして Casio Python プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではありません。いつでもどこでもプログラミングができるプログラム電卓が好きな1ユーザーです。


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

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR