fx-5800P:コマンドの処理速度【再編集】
2013/12/27:
Kenさんのご指摘で、測定がおかしいことが分かり、結果が大幅に間違っていたので、再度測定を行い、内容を再編集した。
Kenさんありがとうございます。
2014/2/5:
fx-5800P の電池を新しくして測定をしたところ、If 文の処理時間が大幅に速くなった。電池の電圧の影響があるようだ。測定値を更新した。
これまで、fx-5800Pで、素因数分解 や もぐら叩きゲーム を作ってみている。
特に、fx-5800Pのような、最低必要限のコマンドを備え、さらに比較的処理速度の遅い電卓でもぐら叩きのようなアクションゲームでは、アルゴリズムや各コマンドの処理速度が重要になってくる。
そこで、幾つかのよく使うコマンドの処理速度を調べてみた。
以下のようなプログラムを作って、処理時間の差から、各コマンドに要するおおよその時間を推定した。
なお時間測定には、ぎょういちろうさん作のフリーソフトウェア SGウォッチ を使用した。
1) Goto 文でのカウントループ
1000→A
Lbl 0
Dsz A
Goto 0
"DONE"▲
処理時間: 6秒
2) If [式] 文を追加したループ
1000→A
Lbl 0
If A≠0:Then
Dsz A
Goto 0
IfEnd
"DONE"▲
処理時間: 16秒
1) のプログラムとの違いは、If [式] ~ Then ~ IfEnd コマンド の有無であり、それにより処理時間が10秒増加している。ループ回数は 1000回なので、If [式] 文実行には 10ミリ秒かかっていると推定される。
If [式] 実行時間: 10ms
3) If [変数] を追加したループ
1000→A
Lbl 0
If A:Then
Dsz A
Goto 0
IfEnd
"DONE"▲
処理時間: 10秒 【修正】
1) のプログラムとの違いは、追加された If [式] ~ Then ~ IfEnd であり、それにより処理時間が4秒増加している。ループ回数1000回なので、If [変数] 文実行には 4ミリ秒かかっている。
If [変数] 実行時間: 4ms
4) Dsz の代わりに A-1→Aにしたループ
1000→A
Lbl 0
A-1→A
If A≠0:Then
Goto 0:IfEnd
"DONE"▲
処理時間: 24秒 【修正】
2) と 4) の処理速度は、Dsz A を A-1→A に置き換えると、8秒遅くなっている。速度を速くしたい場合は、Dsz コマンドを使えば良いことが分かる。こではループ1000回の結果なので、1回の処理の時間差は、8ミリ秒となる。
Dsz A は、A-1→A よりも 8ms 速い
5) If [式] 文の代わりに [式]⇒ にしたループ
1000→A
Lbl 0
A≠0⇒Dsz A
Goto 0
"DONE"▲
処理時間: 15.5秒
1) のプログラムとの違いは、A≠0⇒ が追加されている点であり、処理時間は9.5秒増えている。これは1000回ループの結果なので、A≠0⇒ 1回の実行は15.5ミリ秒。
A≠0⇒ 実行時間: 15.5ms
2) のプログラムよりも5.5秒程度速い。これは1000回ループの結果なので、1回の実行時間は5.5ミリ秒程度速いことが分かる。
[式]⇒ は If [式] 文よりも、5.5ms 速い
6) If [変数] 文の代わりに [変数]⇒ にしたループ
1000→A
Lbl 0
A⇒Dsz A
Goto 0
"DONE"▲
処置時間: 9秒 【修正】
1) のプログラムとの違いは、A⇒ が追加されている点で、処理時間は3秒増えている。これは1000回ループの結果なので、A⇒ 1回の実行は3ミリ秒。
A⇒ 実行時間: 3ms
3) のプログラムよりも9秒速い。これは1000回ループの結果なので、A⇒ は If A 文よりも 1回の実行は9ミリ秒速いことがわかる。
[変数]⇒ は If [変数] よりも 9ms 速い
条件分岐のコマンド If と ⇒ を比べると、⇒ が速いことが分かった。
If 文に比べて、[式]を評価する場合は⇒ 命令の方が、5.5ms 速い。[変数]を評価する場合は、⇒命令は9msとかなり速くなる。
また、デクリメント (変数を1つ減らす) 場合は、A-1→A よりも Dsz A が圧倒的に速いことが分かった。
7) For ループ
For 1000→A To 0
Step -1
Next
"FOR DONE"▲
処理時間: 7秒 【修正】
8) Do ループ
1000→A
Do
Dsz A
LpWhile A
"DONE"▲
処理時間: 6秒
9) While ループ
1000→A
While A
Dsz A
WhileEnd
"DONE"▲
処理時間: 6秒
上記3種類のループコマンドでは、Do ループと While ループが For 文を僅かに抑えて最も速いことが分かった。
10) Do ループ(ループ終了判定に式を使用)
1000→A
Do
Dsz A
LpWhile A≠0
"DONE"
処理時間: 12.5秒
11) While ループ(ループ終了判定に式を使用)
1000→A
While A≠0
Dsz A
WhileEnd
"DONE"
処理時間: 12.5秒
Do ループや While ループの終了判定に式を用いると、処理時間が大幅に長くなることが分かった。
以上まとめると、
1. Goto ループは高速処理に使える
特に、Dsz、Isz、[変数]⇒ と組み合わせるのが良い。
Lbl 0
[何かの処理]
Dsz A
Goto 0
Lbl 0
[何かの処理]
Isz A
Goto 0
Lbl 0
[何かの処理]
Dsz A
A⇒Goto 0
2.条件分岐は、⇒命令が速い
さらに、
A⇒[変数] が A⇒[式]よりもかなり速い
3.ループコマンドは、Do 文、Whiler 文が速い
For 文もほぼ同等だが、若干遅い。
4.Do ループ、While ループは、Goto ループと同等の速さ
Goto ループは、いわゆるスパゲティープログラムになりやすい。コードの可読性も低下する。
従って、無理して Goto ループを使わずとも、Do ループや While ループを使えば良く、それによる速度低下は機にしないで良い。
但し、終了条件にはできるだけ [変数] を用いること。[式]を用いると処理時間が長くなる。
5.Dsz、Isz はループ終了判定に有効
デクリメント(A-1→A) やインクリメント (A+1→A)には、積極的に Dsz や Isz を使うと良い。
これで、fx-5800P 特有の CASIO BASIC のコマンドの選択がはっきりした。
応援クリックをお願いします。励みになるので...
Kenさんのご指摘で、測定がおかしいことが分かり、結果が大幅に間違っていたので、再度測定を行い、内容を再編集した。
Kenさんありがとうございます。
2014/2/5:
fx-5800P の電池を新しくして測定をしたところ、If 文の処理時間が大幅に速くなった。電池の電圧の影響があるようだ。測定値を更新した。
これまで、fx-5800Pで、素因数分解 や もぐら叩きゲーム を作ってみている。
特に、fx-5800Pのような、最低必要限のコマンドを備え、さらに比較的処理速度の遅い電卓でもぐら叩きのようなアクションゲームでは、アルゴリズムや各コマンドの処理速度が重要になってくる。
そこで、幾つかのよく使うコマンドの処理速度を調べてみた。
以下のようなプログラムを作って、処理時間の差から、各コマンドに要するおおよその時間を推定した。
なお時間測定には、ぎょういちろうさん作のフリーソフトウェア SGウォッチ を使用した。
1) Goto 文でのカウントループ
1000→A
Lbl 0
Dsz A
Goto 0
"DONE"▲
処理時間: 6秒
2) If [式] 文を追加したループ
1000→A
Lbl 0
If A≠0:Then
Dsz A
Goto 0
IfEnd
"DONE"▲
処理時間: 16秒
1) のプログラムとの違いは、If [式] ~ Then ~ IfEnd コマンド の有無であり、それにより処理時間が10秒増加している。ループ回数は 1000回なので、If [式] 文実行には 10ミリ秒かかっていると推定される。
If [式] 実行時間: 10ms
3) If [変数] を追加したループ
1000→A
Lbl 0
If A:Then
Dsz A
Goto 0
IfEnd
"DONE"▲
処理時間: 10秒 【修正】
1) のプログラムとの違いは、追加された If [式] ~ Then ~ IfEnd であり、それにより処理時間が4秒増加している。ループ回数1000回なので、If [変数] 文実行には 4ミリ秒かかっている。
If [変数] 実行時間: 4ms
4) Dsz の代わりに A-1→Aにしたループ
1000→A
Lbl 0
A-1→A
If A≠0:Then
Goto 0:IfEnd
"DONE"▲
処理時間: 24秒 【修正】
2) と 4) の処理速度は、Dsz A を A-1→A に置き換えると、8秒遅くなっている。速度を速くしたい場合は、Dsz コマンドを使えば良いことが分かる。こではループ1000回の結果なので、1回の処理の時間差は、8ミリ秒となる。
Dsz A は、A-1→A よりも 8ms 速い
5) If [式] 文の代わりに [式]⇒ にしたループ
1000→A
Lbl 0
A≠0⇒Dsz A
Goto 0
"DONE"▲
処理時間: 15.5秒
1) のプログラムとの違いは、A≠0⇒ が追加されている点であり、処理時間は9.5秒増えている。これは1000回ループの結果なので、A≠0⇒ 1回の実行は15.5ミリ秒。
A≠0⇒ 実行時間: 15.5ms
2) のプログラムよりも5.5秒程度速い。これは1000回ループの結果なので、1回の実行時間は5.5ミリ秒程度速いことが分かる。
[式]⇒ は If [式] 文よりも、5.5ms 速い
6) If [変数] 文の代わりに [変数]⇒ にしたループ
1000→A
Lbl 0
A⇒Dsz A
Goto 0
"DONE"▲
処置時間: 9秒 【修正】
1) のプログラムとの違いは、A⇒ が追加されている点で、処理時間は3秒増えている。これは1000回ループの結果なので、A⇒ 1回の実行は3ミリ秒。
A⇒ 実行時間: 3ms
3) のプログラムよりも9秒速い。これは1000回ループの結果なので、A⇒ は If A 文よりも 1回の実行は9ミリ秒速いことがわかる。
[変数]⇒ は If [変数] よりも 9ms 速い
条件分岐のコマンド If と ⇒ を比べると、⇒ が速いことが分かった。
If 文に比べて、[式]を評価する場合は⇒ 命令の方が、5.5ms 速い。[変数]を評価する場合は、⇒命令は9msとかなり速くなる。
また、デクリメント (変数を1つ減らす) 場合は、A-1→A よりも Dsz A が圧倒的に速いことが分かった。
7) For ループ
For 1000→A To 0
Step -1
Next
"FOR DONE"▲
処理時間: 7秒 【修正】
8) Do ループ
1000→A
Do
Dsz A
LpWhile A
"DONE"▲
処理時間: 6秒
9) While ループ
1000→A
While A
Dsz A
WhileEnd
"DONE"▲
処理時間: 6秒
上記3種類のループコマンドでは、Do ループと While ループが For 文を僅かに抑えて最も速いことが分かった。
10) Do ループ(ループ終了判定に式を使用)
1000→A
Do
Dsz A
LpWhile A≠0
"DONE"
処理時間: 12.5秒
11) While ループ(ループ終了判定に式を使用)
1000→A
While A≠0
Dsz A
WhileEnd
"DONE"
処理時間: 12.5秒
Do ループや While ループの終了判定に式を用いると、処理時間が大幅に長くなることが分かった。
以上まとめると、
1. Goto ループは高速処理に使える
特に、Dsz、Isz、[変数]⇒ と組み合わせるのが良い。
Lbl 0
[何かの処理]
Dsz A
Goto 0
Lbl 0
[何かの処理]
Isz A
Goto 0
Lbl 0
[何かの処理]
Dsz A
A⇒Goto 0
2.条件分岐は、⇒命令が速い
さらに、
A⇒[変数] が A⇒[式]よりもかなり速い
3.ループコマンドは、Do 文、Whiler 文が速い
For 文もほぼ同等だが、若干遅い。
4.Do ループ、While ループは、Goto ループと同等の速さ
Goto ループは、いわゆるスパゲティープログラムになりやすい。コードの可読性も低下する。
従って、無理して Goto ループを使わずとも、Do ループや While ループを使えば良く、それによる速度低下は機にしないで良い。
但し、終了条件にはできるだけ [変数] を用いること。[式]を用いると処理時間が長くなる。
5.Dsz、Isz はループ終了判定に有効
デクリメント(A-1→A) やインクリメント (A+1→A)には、積極的に Dsz や Isz を使うと良い。
これで、fx-5800P 特有の CASIO BASIC のコマンドの選択がはっきりした。
応援クリックをお願いします。励みになるので...