りょうのゲーム塾 -19ページ目

りょうのゲーム塾

再開、準備中。

数値変数をフラグ変数として活用するためには
2進数の演算(論理演算)を理解する必要があります。

これについても過去記事を参照していただきたいのですが
ここで簡単に説明しておきましょう。

論理演算は2進数値の演算です。
2進数は0と1だけで表現されています。

基本的な演算は次の通りです。



■論理和(OR)
論理和は条件の判断などで使う『または』と同じです。
『または』とは2つの条件のうちどちらか一方が成り立てば
この条件は成り立つという意味です。
論理演算では0を偽もしくはFALSE、1を真もしくはTRUEといいます。
TRUEは条件が成り立つ、要するにOKって事です。
FALSEは条件が成り立たない、要するにNGって事です。
2つの2進数の組み合わせは4通りありますね。
各組み合わせで論理和を考えると下記の通りになります。


A OR B = 結果
======================
0    0    0
0    1    1
1    0    1
1    1    1



■論理積(AND)
論理積は条件の判断などで使う『かつ』と同じです。
『かつ』とは2つの条件が両方ともに成り立てば
この条件は成り立つという意味です。
各組み合わせで論理積を考えると下記の通りになります。


A AND B = 結果
======================
0     0    0
0     1    0
1     0    0
1     1    1



■排他的論理和(XOR)
排他的論理和は論理和ににています。
各組み合わせで論理積を考えると下記の通りになります。


A XOR B = 結果
======================
0     0   0
0     1   1
1     0   1
1     1   0 ←ここが違います


OR演算子との違いはOR演算子はどちらか一方または両方成り立てば
成り立つだったのがこの排他的論理和ではどちらか一方だけが成り立てば
この条件は成り立ちます。



■否定(NOT)
今までの演算子は2つの2進数値が必要な2項演算子でしたが
このNOTは単項演算子といい1つの2進数値が必要です。
否定は条件の反転を行います。


NOT A = 結果
======================
0       1
1       0


これらの論理演算(プチコンではビット演算)をどのようにして使えば
フラグ処理ができるのかを次回説明します。



■フラグって何?
そもそもここで言うフラグとは旗の意味です。
要するに旗が揚がっているかいないかと言う事を表しています。
通常フラグが揚(上)がっている状態を1、
フラグが下がっている状態を0として扱います。

1と0でONまたはOFF、あるかないかの2値を表します。


■フラグ変数と数値変数はどう違うのか?
フラグ変数として数値変数を使います。
使い方によっては同じものです。

0001 FLAG=0
0002 GOSUB @FLAGDISP
0003 FLAG=1
0004 GOSUB @FLAGDISP
0005 END
0006 @FLAGDISP
0007 IF FLAG==1 GOTO @L_OK
0008 'NG
0009 PRINT "FLAG=";FLAG;" ON"
0010 RETURN
0011 'OK
0012 @L_OK
0013 PRINT "FLAG=";FLAG;" OFF"
0014 RETURN

このプログラムで使っている変数FLAGは数値変数です。
0もしくは1を代入して使っている限りフラグとして機能しています。
しかしこのままでは変数1個でひとつのフラグの状態しか保持できません。


■フラグの値は2進数1ビットで表せる。
フラグの値は0もしくは1で表します。
プチコンではこれを実際にシステム変数TRUEとFALSEで設定していますね。
しかしプチコンの数値変数は32ビットでそのうちの20ビットが整数部を表し、
そのうち最上ビットは符号ビットという特殊なビットなので
実際には19ビット使う事が出来ます。

これは言い換えると19個のフラグとして使えるということです。


■フラグの処理を考える
それでは具体的にフラグをどうやって使うかですが、
フラグは基本次のような処理が出来れば問題ありません。

1)フラグをONにする
2)フラグをOFFにする
3)フラグを判断する


それではサンプルをみてみましょう。


0001 FLAG=0 ←フラグをONにする
0002 GOSUB @FLAGDISP
0003 FLAG=1 ←フラグをOFFにする
0004 GOSUB @FLAGDISP
0005 END
0006 @FLAGDISP
0007 IF FLAG==1 GOTO @L_OK ←フラグを判定する
0008 'NG
0009 PRINT "FLAG=";FLAG;" ON"
0010 RETURN
0011 'OK
0012 @L_OK
0013 PRINT "FLAG=";FLAG;" OFF"
0014 RETURN


基本的なフラグ処理が使われていますね。
しかしこのままでは変数FLAGは数値0と数値1しか使っていません。
1個のフラグしか処理されていない事になります。


それではプチコンの数値変数について復習してみましょう。

1)プチコンの数値変数は32ビットである
2)固定小数点方式を使っている
3)整数部は20ビットで最上位は符号ビットである
4)小数部は12ビットである

ここで簡単なサンプルを実行してもう少し理解をしてみましょう。


■サンプル1
0001 A=&H00000 '&B 0000 0000 0000 0000 0000
0002 B=&H00001 '&B 0000 0000 0000 0000 0001
0003 C=&H00002 '&B 0000 0000 0000 0000 0010
0004 PRINT "A=";A
0005 PRINT "B=";B
0006 PRINT "C=";C
0007 END


このプログラムの注釈は入力しないでください。
何の意味もありません。
書かれている16進数を2進数で表しています。

今までこのブログを読んでいただいた方でも
まだ16進数や2進数に馴染みがないという人は当然ですが
今回はどうしても理論的には2進数を理解する必要があります。
もし基礎的な事が知りたければ過去記事を参照してくださいね。

このサンプルは数値変数に16進数値を代入して表示するものです。
実行するとどうなるかは分かりますか?


■実行結果
A=0
B=1
C=2
OK


そうですね。
10進数の0,1,2となります。


■サンプル2
0001 A=&H7FFFF '&B 0111 1111 1111 1111 1111
0002 B=&H80000 '&B 1000 0000 0000 0000 0000
0003 C=&H80001 '&B 1000 0000 0000 0000 0000
0004 PRINT "A=";A
0005 PRINT "B=";B
0006 PRINT "C=";C
0007 END


では今度のサンプルはどうなるでしょうか?
過去記事から16進数と2進数および10進数の関係が分かっているとすると
16進数の&H7FFFFの次の値が&H80000であり、
&H80000の次の値が&H80001になります。
これを表示すると。。。


■実行結果
A=524287
B=-0
C=-524287
OK


ここが数学の数値表現とコンピュータの数値表現との違いです。
確かに&H7FFFFは10進数524287になります。
なので&H80000は10進数524288にならなければなりません。
ところが実際にはー0(?)という表示になっています。

まずはー0って何んだろうと思う人もいて当然です。
しかしこれはプチコンの仕様なのです。

そして&H80000の次の値が&H80001なのですが
これはー524287になっています。

プチコンは整数部分の一番左端(最上位ビットという)を符号ビットとして扱っています。
ここが0の時は正の値、1の時は負の値という判断をしています。

なんで正の値の最大値が&H7FFFFとなります。
負の値については最上位が1になるわけです。

実はこの考え方から&H80000は符号が1なので負の値となり
その他のビットが0要するに0なので-0という表現になっています。


■サンプル3
0001 A=&HFFFFE '&B 1111 1111 1111 1111 1110
0002 B=&HFFFFF '&B 1111 1111 1111 1111 1111
0003 C=B+1 '&B 0000 0000 0000 0000 0000
0004 PRINT "A=";A
0005 PRINT "B=";B
0006 PRINT "C=";C
0007 END


負の値の表現を2の補数表現といいますがこれも過去記事を参照してください。
このサンプルは問題がないことを証明するプログラムです。


■実行結果
A=-2
B=-1
C=0
OK



■サンプル4
0001 A=&H7FFFF '&B 0111 1111 1111 1111 1111
0002 B=A+1 '&B 1000 0000 0000 0000 0000
0003 PRINT "A=";A
0004 PRINT "B=";B
0005 END

さて最後にサンプル3と同じプログラムの値を変更して実行してみましょう。


■実行結果
Overflow (2)
OK


するとどうでしょうか?
&H7FFFFの次の値は&H80000だったので&H7FFFFに1を足してみたのですか
結果は2行目にオーバーフローのエラーがでました。
オーバーフローとはオーバー(越えて)フロー(溢れる)という意味です。
正の最大値を越えたという意味です。