プチコン3号入門講座

論理式で深まる条件判断


論理式とは何なのか



 「IF〜THEN〜による条件判断」において「条件式が成立している時にTHEN以下を実行する」ということを書きました。このような条件式==!=などの比較演算子が含まれた式)のことは論理式とも言います。
 プチコン3号で初めてプログラミングに挑戦する初心者には理解するのが難しい部分もありますが、初心者が中級者や上級者へとステップアップする際には必要不可欠な要素となるため覚えておくと良いでしょう。

 この論理式において条件が成立した状態はtrue(トゥルー)と呼ばれプチコン3号の場合は値が1になります。また条件が不成立の状態はfalse(フォールス)と呼ばれ値は0になります。(ちなみにプチコン3号ではシステム変数TRUEには1という値、システム変数FALSEには0という値が入っている)

 《 論理式におけるtrueとfalse 》
 条件式成立 → true(トゥルー) 値は 1 になる
 条件式不成立 → false(フォールス) 値は 0 になる

 これについて簡単に解説します。
 例えばRPGにおいて現在のHPが10とします。変数HPに現在のHPが入っているとします。HP=10とする)
 では、死亡判定を行いたいと思います。現在のHPは0より大きいでしょうか?
 これはIF命令を使えば IF HP>0 THEN 〜 と記述できますね。この条件が成立しているかどうかは、HP>0という論理式の値を見れば分かるのです。

 では、PRINT HP>0 としてみてください。画面には1と表示されましたね。つまり、これはこの条件であるHP>0が成立しているためです。
 次にHP=0としたあとに同様に PRINT HP>0 としてみてください。画面には0と表示されましたね。つまり、これはこの論理式が不成立であるためです。
 論理式は式の値が10かで表すことができるということが分かったと思いますが、これが一体何の役に立つのかと思っている人もいるかもしれないので実例を挙げます。

 これは画面の左から右に向かって"♥"マークが軌跡を残しながら移動するプログラムです。

ACLS
X=0
@LOOP
LOCATE X,0:PRINT "♥"
X=X+1
VSYNC 3
GOTO @LOOP

画面外をLOCATEで指定できないのですぐにエラーとなってしまいます。画面外に出ないためには画面内にいる時だけX=X+1を実行するという方法が必要になるでしょう。これはIF命令を使って判断することもできますが、論理式を使えば次のようにできます。

ACLS
X=0
@LOOP
LOCATE X,0:PRINT "♥"
X=X+(X<49)
VSYNC 3
GOTO @LOOP

 LOCATEで指定できるX座標の最大値は49なのでX<49の時のみX=X+1を実行すれば良いことが分かりますね。X=49の時はX<49の値は0になるためX=X+0になり、X座標の値が加算されることはなく画面端で"♥"マークの動きは止まります。
 比較演算は四則演算よりも優先順位が低いためX=X+(X<49)という式をX=X+X<49のようにカッコを省略するとX=(X+X)<49と認識されてしまうため注意が必要です。X+Xの値が49より小さければXの値は1になり、そうでなければ0になるという動作になってしまうためXの値は0で固定となり画面の左から"♥"マークは動かない)

 論理式を使えばこのようなこともできます。
 RPGにおいて「メダルを1枚持っていれば1ゴールドと交換」「2枚持っていれば3ゴールドと交換」「3枚以上持っていれば10ゴールドと交換」というイベントがあるとしましょう。現在のゴールドが変数G、持っているメダルの枚数が変数Mに入っている場合はIF命令を使うと3通りの判断が必要になってきます。

IF M==1 THEN G=G+1
IF M==2 THEN G=G+3
IF M>=3 THEN G=G+10

 これは論理式で書き直すとこのようになります。

 G=G+(M==1)+(M==2)*3+(M>=3)*10

 この論理式で表したものがIF命令を組み合わせたものと本当に同じ動作になっているのかを検証してみます。
 M=1の時は(M==1)の値は1(M==2)の値は0(M>=3)の値は0なのでG=G+1となります。
 M=2の時は(M==1)の値は0(M==2)の値は1(M>=3)の値は0なのでG=G+3となります。
 M=3の時は(M==1)の値は0(M==2)の値は0、(M>=3)の値は1なのでG=G+10となります。
 これでIF命令を使ったものと同じ動作になっているのが分かると思います。

 このようにtrueの時は1falseの時は0の値になる論理式を使うとIF命令で記述するよりもすっきりとした記述が可能になる場合もあるため覚えておくと良いでしょう。

 また複数の条件を満たしているかを判定する際には論理式の値がtrueの時は1、falseの時は0の値を取るということが分かっていれば「両方を満たしている」場合は「*」、「どちらかを満たしている」場合は「+」で代用が可能になります。

 IF A>1 AND B>2 THEN 〜 → IF (A>1)*(B>2) THEN 〜
 IF A>1 OR B>2 THEN 〜 → IF (A>1)+(B>2) THEN 〜

 なぜ、このようなことが可能なのかというと下記のようにIF命令では条件の部分の値が「0以外か」「0か」でTHEN以下を実行するかが決まるためです。(比較演算はすでに何度も書いているように演算優先順位が低いためカッコを付けるのが必須でIF A>1 * B>2 THEN 〜のようにカッコを省略した場合には論理式A>1の値を計算するのではなくA>1*Bの値を計算して(その結果)>2となり、条件式の値は01かしか取らないため2より大きくなることはなく常にfalseの条件式になってしまう。)
 プチコン3号には複数の条件式においては「かつ」「または」に相当する演算子が用意されているためわざわざ四則演算の演算子を使う必要はないのですが、複数の条件式のうち指定した数だけ満たす場合などには活用できます。
 例えば、5つの条件式のうち任意の2つ以上の条件式を満たしている場合のみTHEN以下を実行したい場合は次のようになります。(これを普通に判断するならば複数のIFを使っていくつの条件式を満たしているかをカウントする必要がある)

 IF (A>1)+(B>2)+(C>3)+(D>4)+(E>5)>=2 THEN 〜

 これは特殊な書き方であるため初心者が無理に覚える必要はなくこのページに書いていることが粗方理解できるようになってからでも遅くありません。
 条件判断には様々な方法があり、正しく動作していればどのように書いても問題ありません。しかし、正しい動作をさせるためには何度も書いているように「比較演算を省略しない」というのが最も近道になるということは覚えておくと良いでしょう。


 実は数値に限らず文字列であっても比較演算が可能です。例えばA=(A$==B$)と記述した場合は変数A$と変数B$の文字列が一致した場合にAの値は1になり、そうでない場合は0になります。
 では、A=(A$>B$)と記述した場合はどうなるでしょうか。数値と違って文字列には大小関係はありませんが比較演算を行った場合にはキャラコードの大小を比較を行います。A$="A"B$="B"ならば、A$のキャラコードよりもB$のキャラコードの方が大きいためA=(A$>B$)においてAの値は0となります。
 複数の文字で構成された文字列同士の比較であれば先頭から順番に1文字ずつ比較していってキャラコードの大小関係が比較されます。文字数が異なる場合はどうなるかというと例えばA$="ABC"B$="AB"の場合は先頭の2文字が一致していますが、3文字目を見るとB$には比較すべき文字がないためB$の方が小さいと判断されます。文字数が少なくてもA$="ABC"B$="AC"のような場合だと2文字目の時点でB$の方が大きいことが決定するため文字数の違いは影響ありません。
 あと配列変数を使った比較演算の場合は添え字を付ける必要があります。複数の値と複数の値を単純比較はできないので当たり前のことに感じるかもしれませんが、要素数1の配列変数A[]B[]においてC=(A>B)のような比較演算もできず、配列全体を示す場合は比較演算を行うことはできないと覚えておいた方が良いでしょう。もちろん、C=(A[0]>B[0])のように1要素ずつの比較演算であれば何ら問題はありません。

 それでは、文字列と数値の比較演算ではどうなるでしょうか?
 例えばA$>Bのような比較演算は本来であれば行うことができないためエラーになります。しかし、プチコン3号においては現時点は文字列と数値の比較演算を行うと3になるという仕様(一種の裏技)になっています。これは正式な仕様ではなく将来的には変更の恐れがありますが、これを利用すると変数の型をプログラム実行中に判断が可能になります。

《 型を取得するSUFFIX()関数 》
DEF SUFFIX(V)
VAR A
A=V>0<3
IF A THEN V=0.5:A=V*2+1
RETURN A
END
※この関数では整数型は1、実数型は2、文字列型は0を返す

 型が判別できるとどういうメリットがあるかというと例えばDEFを使って自作関数を作る場合には引数に文字でも数値でも受け付ける関数を作ることが可能になる(詳しくは後述のDEFで自作関数を作ろう」を参照)ということです。それ以外のメリットはあまりなくむしろエラー表示を行わないため思わぬバグを産んでしまう可能性がある(例えばA$>B$と記述しなくてはならない場面でA$>Bと記述してもエラーにならないため誤動作の原因がどのにあるのか気づかない)というわけで、文字列と数値との比較演算は現時点ではエラーにならないというのは覚えておいた方が良いかも知れません。それを知っていれば「もしかするとタイプミスで文字列と数値の比較演算を行っているのでは?」という感じで誤動作の原因を見つけやすくなります。
 あと知っておく必要があるのはA$>Bのように文字列と数値との比較演算は3を返すのですが、A>B$のように数値と文字列との比較演算はType mismatchエラーになるということです。この「比較演算で3を返す」裏技を使いたい人はエラーにならないように気を付けましょう。


IF命令は「0以外か」「0か」でTHEN以下を実行するか否かが決まる



 上記のようにIF命令における条件式(論理式)は成立(true)の時は1不成立(false)の時は0の値をとるのですが、これは言い換えると成立時には IF 1 THEN 〜 、不成立時には IF 0 THEN 〜 という動作をしているとも言えます。
 これが非常に重要になってくることで実はIF命令は条件式の部分の値が「0以外か」「0か」でTHEN以下を実行するか否かが決まっているのです。これは論理式においてはtrueの時は1という値になるのですがコンピュータ(プチコン3号)が処理する場合には0以外の値はtrueとして認識されるためです。

 では、分かりやすい例としてボタン入力判定について考えてみましょう。ボタン入力判定は「ボタンやスライドパッドでキャラを動かしてみよう」で詳しく書いているのですでに理解できていると思いますが、今回はより簡略化した記述方法や動作の仕組みについて書いてみます。
 例えば(他に押しているボタンに影響されず)Aボタンを押している間はBEEPを鳴らすには、(変数BBUTTON()関数の値が入っている場合)IF (B AND 16)==16 THEN BEEPと記述しますが、これはAボタンを押している場合は論理式 (B AND 16)==16 の値は1になるためTHEN以下が実行されるわけです。

 ここではAボタンを押しているか否かという二択しかなくAボタンを押している時はB AND 16の値は16になり、押してない時は0になります。このように「0か」「0以外か」で判断が可能な場合においては比較演算(「==16」の部分)を省略してIF B AND 16 THEN BEEPと記述することができます。
 これはAボタンを押している時はIF 16 THEN BEEPという処理、Aボタンを押していない時はIF 0 THEN BEEPという処理になっているため比較演算を省略しても全く同一の動作になっていることが分かると思います。IF命令においてTHEN以下が実行されるのはIFTHENの間の値が0以外の場合となるため)

 この IF B AND 16 THEN 〜 のような記述をしているプログラムは非常に多く見かけると思いますが、これだけの過程を経てこのような判定が行われているわけです。

 比較演算を省略できるのは「0か」「0以外か」という二択の場合に限られます。例えばB AND 16の場合はAボタンを押しているか否かという二択しか選択肢がありませんでしたが、ABボタンを両方押しているかどうかを判定するのにB AND 48とした場合にはIF (B AND 48)==48 THEN BEEPと記述したときとIF B AND 48 THEN BEEPと記述したときでは結果が変わります。それは後者のAボタン、もしくはBボタンのいずれか片方を押している場合でもTHEN以下が実行されてしまうからです。Aボタンを押している時はB AND 48の値は16、Bボタンを押している時はB AND 48の値は32となり「0以外」となるためTHEN以下が実行される)

 ここで「ボタンやスライドパッドでキャラを動かしてみよう」で書いたこのイメージ図を見直してみましょう。

【 比較演算を省略した場合のイメージ 】




 このイメージ図を見ながら上記の説明を読めば比較演算を省略した場合には「0か」「0以外か」というのがどのような状態かが分かると思います。B AND 48AボタンとBボタンが押された状態を判定しようと思ったらどちらか(どれか)が押されたら成立するという条件になってしまうのが一目瞭然ですね。指定したボタンのうちどれかが押されていたら成立という条件にしたいならば比較演算を省略しても問題ありません。
 ただし、下記のように複数の条件を結合して判断する場合には比較演算を省略すると不都合が発生する場合があります。

 さて、比較演算を省略した場合は「0か」「0以外か」で判断するため変数Aの値は0で無いときにTHEN以下を実行するという場合には IF A!=0 THEN 〜IF A THEN 〜 と比較演算を省略して記述可能なことが分かりますね。
 では、変数Aの値が1で無いときにTHEN以下を実行する場合にはIF A!=1 THEN 〜 は比較演算を省略可能なのでしょうか?
 実はこれは IF A-1 THEN 〜 とすることができます。これは、Aの値が1の時はA-1の値は0になり、そうで無いときは0以外になるためです。つまり、「0か」「0以外か」という二択になるため比較演算が省略可能というわけです。

 ここまで読めばどのような場合に比較演算を省略可能かが分かったと思います。どのような場合に省略可能なのか分からないときは比較演算は省略しないということが誤動作をしないためには必要不可欠となります。
 詳しい理由はよく分からなくてもIF命令は条件式の部分の値が「0か」「0以外」かでTHEN以下が実行されるかどうかが決まるということは他人が作ったプログラムを読む場合において必要になることが多いためぜひ覚えておいてください。



IF命令におけるANDとORの使用上の注意



 IF命令においては複数の条件式がすべて成立するか否かはANDを使い、いずれかが成立するか否かはORを使うということを「IF〜THEN〜による条件判断」において書きましたが、ここでの「AND」「OR」はボタン入力判定で使用することがあるANDと同一のものです。(「ビット演算子」と呼ばれているもの)

 例えばIF A==1 AND B==2 THEN 〜 のような2つの条件がIF命令によって記述されていて両方が成立する場合にはIF 1 AND 1 THEN 〜と処理されているわけです。ここでPRINT 1 AND 1とすればその値が1になることからIF 1 THEN 〜となるため上記のようにTHEN以下が実行されることが分かると思います。

 実際にDIRECTモードで実行してみれば分かりますがANDORは下記のように計算されます。

1 AND 1 = 11 AND 0 = 00 AND 1 = 00 AND 0 = 0
1 OR 1 = 11 OR 0 = 10 OR 1 = 10 OR 0 = 0
※この計算については後述の「ビット演算」で詳しく書いています

 この計算結果を全部覚える必要はありません。ANDは「論理積」、ORは論理和と呼ばれているのですが、「ANDは掛け算」「ORは足し算」と覚えておけば分かりやすいと思います。(実際、上記のように比較演算を省略せずに書いた条件式においてはANDOR*+で代用可能だし)
 1 AND 0の値は0ですが1×0=0なので簡単ですね。1 OR 0の値は1ですがこれも1+0=0なので簡単ですよね。1+1=2だけどここでは1として扱うという点さえ注意すれば良い)
 これによって複数の条件式を記述した場合にはどのように処理されているのかが分かるようになりますが、ここで問題となるのは条件式の比較演算を省略した場合についてです。

 AボタンとBボタンを両方押している場合というのは変数BBUTTON()関数で取得した値が入っている時にはIF (B AND 48)==48 THEN 〜となるのは分かると思いますが「A、Bボタンを両方押している」というのは、「Aボタンを押している」かつ「Bボタンを押している」と考えることができます。
 したがって、IF (B AND 16)==16 AND (B AND 32)==32 THEN 〜と記述できます。

 ここで「B AND 16(Aボタンを押しているか否か)」、「B AND 32(Bボタンを押しているか否か)」は、それぞれ「16」か「0」「32」か「0」という値になり、「0以外か」「0か」という二択になるため比較演算を省略可能に思えます。

 IF (B AND 16) AND (B AND 32) THEN 〜

 しかし、この条件式は決して成立することがないのです。
 それは、ABボタンを両方押した時には16 AND 32となるわけですが、16 AND 32の値は0になるためです。本当にそうなるのかはDIRECTモードで確かめてみれば一目瞭然です。

 条件式それぞれが「0か」「0以外か」で判断可能であってもANDORを使って複数の条件を判断する場合には比較演算を省略してはならないというのがこれで分かると思います。(比較演算を記述してそれぞれの条件が0か1かという値を取る場合に限り、ANDやORを使って複数の条件を判断可能になる)
 これは複数の条件判断でANDやORを使う場合には比較演算を省略しなければいいだけのことであり、難しく考える必要はありません。


論理演算子 ||と&&で正しく条件判断



 「論理積」「論理和」という名称通りANDORは論理演算を行う演算子ですが、2進数で考えた場合に各桁同時に論理演算を行います。それ故に「ビット演算子」なのですが、結果がtruefalseのどちらかにはならない場合も出てきます。
 例えば 5 AND 6 の値(560以外であるためtrue)は4になり結果はtrueですが、5 AND 8 の値はtrue同士の演算にもかかわらず結果は0false)になります。
 したがって、条件式の値がtruefalseかが重要なIF命令において「0」「1」以外の値を取るANDORを記述すると想定していない状況になる可能性があるわけです。とはいえ、比較演算を行えば基本的には「0」か「1」という値になります。したがって、IF命令においてANDやORで複数条件を記述する場合には比較演算が必要になるというわけです。

 ということで、IF命令において上記のようにANDORを使って複数の条件を記述した場合に各条件が成立していても(trueの状況下でも)比較演算を省略した場合には本来求めている動作をしないという問題があります。
 しかし、そのような場合でも正しく判断が可能になる方法としてはビット演算子であるANDORを使って判断するのではなく論理専用に用意されている演算子を使うという方法があります。
 論理演算の演算子として、プチコン3号では「かつ」を表すのに"&&"「または」を表すのに"||"という演算子が使えます。(注意:形は少し違いますが、「または」を表す||という記号はキーボードのAキーの左にある記号を二つ並べたものを示している)

《 論理演算子の使用例 》
A<1 かつ B>2
 IF A<1 && B>2 THEN 〜
A<1 または B>2
 IF A<1 || B>2 THEN 〜


《 論理演算子 "&&" と "||" の演算結果 》
true && true = 1(true)true && false = 0(false)false && true = 0(false)false && false = 0(false)
true || true = 1(true)true || false = 1(true)false || true = 1(true)false || false = 0(false)
※ここでのtrue0以外の値を示す

 この論理演算子を使って「Aボタンを押している」かつ「Bボタンを押している」場合というのを記述すると変数BBUTTON()関数の値が入っている場合は下記のようになります。

 IF (B AND 16) && (B AND 32) THEN 〜
  ※論理演算子(&&||)は演算優先順位が低いためカッコは省略できるけど分かりやすくするためあえて付けている

 この条件式でABボタンの両方を押した場合には IF 16 && 32 THEN 〜 という処理が行われるわけですが、論理演算子"&&"true && true = 1 と処理されるため IF 1 THEN 〜 となりTHEN以下が実行されます。(Aボタンは押しているけどBボタンを押してない場合はIF 16 && 0 THEN 〜となりtrue && false = 0であるためTHEN以下は実行されない)

 変数Tの値が3より小さくてABボタンを両方押している時というのをこのように記述したとします。

 IF T<3 && B AND 48 THEN 〜

 論理演算子は0以外の値はtrueとすることで正しく演算が可能なのですが、上記のようにABボタンを両方押した場合に48(0以外の値)になるだけではなくAボタン、Bボタンのみを押した場合でも0以外の値になってしまうためB AND 48では「ABボタンを両方押しているか否か」の正しい判断はできません。B AND 48では「ABボタンをいずれか押しているか否か」という意味になってしまう)
 そのためB AND 48の部分は比較演算子を省略せずに (B AND 48)==48 と記述するか、B AND 16 && B AND 32 のように「0以外か」「0か」の正しい判別が可能になるようにしなくてはなりません。
 ちなみにプチコン3号では文字列変数の判定を行う際に比較演算を省略した場合は必ずtrueになってしまいます。つまり、文字列変数を使った判定を正しく行うためには比較演算が常に必須となるわけです。IF A$!=""THEN 〜IF A$ THEN 〜 と記述すると誤動作してしまう)

 あと"&&"で複数条件を記述した場合には"AND"と異なる点としては"&&"では1つ目の条件がfalseになった場合には複数の条件を演算した結果はfalseになることが確定するため2つ目以降の判断は行わないという点が挙げられます。これは「ショートカット(短絡評価)」と呼ばれているものです。||は1つ目の条件がfalseになった場合は2つ目以降は判断が行わない)
 この違いの分かりやすい例としてASC(INKEY$())を使ったものを書いておきます。

ANDを使った場合 → エラーが発生
@LOOP
 K$=INKEY$()
 IF K$!="" AND ASC(K$)>64 THEN BEEP
 VSYNC
GOTO @LOOP

&&を使った場合 → 正しく判断が可能
@LOOP
 K$=INKEY$()
 IF K$!="" && ASC(K$)>64 THEN BEEP
 VSYNC
GOTO @LOOP
※2つのプログラムは青字の部分以外は同一です。

 解説するとASC()は文字列のキャラコードを返す関数ですが、その文字列が何もない、つまり、""(null)の場合はIllegal function callというエラーが出てしまいます。何もキー入力をしていない場合は当然K$に何も入ってないためASC(K$)を求めようとするとエラーが出るわけです。  しかし、&&を使った場合にはK$!=""の時(何もキー入力がない時)ASC(K$)>64trueでもfalseでも関係ないため実行されないためエラーが出ることもありません。(実行されないということは当然処理速度の向上にも繋がる)
 論理演算子&&を使わずにこれを正しく判断するには IF K$!="" THEN IF ASC(K$)>64 THEN BEEP のように記述する必要があります。
 これ以外にも「&&ではfalseになった時点でそれ以下の式を評価しない」というのは活用できる場面はたくさんあります。例えば配列変数の添字が範囲内かどうかをチェックする場合でも1つ目の条件式で添字の値をチェックしておけば良いです。したがって、「AND&&は同じように使える場面がある」というだけであって「同じものである」という認識はしない方が良いです。(条件式の「かつ」としてAND&&を使い分ける必要はなくtruefalseがどのようなものかが分かった時点でANDではなく&&を使用するようにすれば良いだけ)

 また、論理演算子にはtruefalseを反転する"!"(論理否定 もしくは 論理反転)があります。これはより正確に言うならば「01にする」「0以外を0にする」演算子です。
 IF A!=0 THEN 〜IF A THEN 〜 と記述が可能でしたが、IF A==0 THEN 〜IF !A THEN 〜 と記述が可能になるのです。!Aの値はA0の時は1になり、A1の時0以外の時)0になるためです。
 この論理反転「!」を使えば例えば特定の条件がありそれが成立しない場合のみ実行したい時はその条件式に「!」を付けるだけで済みます。例えば「A>99でない場合」に実行したいというのであれば「!(A>99)」という条件にすれば良いということです。
 例えば変数Aの値が50の場合は論理式A>99の値は0になりますが、「!」は上記のように「01にする」「0以外を0にする」という演算子であるため!(A>99)の値は1になりIF !(A>99) THEN 〜と記述した場合には(条件式の値が0以外であるため)THEN以下が実行されるわけです。

 この論理反転を使えば「Aボタンを押している」かつ「Bボタンを押していない」場合というのは下記のように記述できます。

 IF B AND 16 && !(B AND 32) THEN 〜
  ※変数BにBUTTON()関数の値が入っている場合
  論理反転は演算優先順位が高いため B AND 32 の方にはカッコが必要になる


 論理演算子"&&""||"truefalseで簡単に演算ができるため複数の条件を記述したい場合には初心者にもオススメできるのですが、「0以外」がtrueになるようにしておかないと正しい判断はできないという点だけは注意をしておく必要があります。0以外がtrueとなるためB AND 48のように自分が思っているような判断ができない場合がある)
 IF命令において複数の条件を記述する場合には論理演算子ではなくビット演算子であるANDORを使うのは「かつ」「または」の表現としては本来は正しくありませんが比較演算子を省略しなければ正しい判断が可能になり初心者には分かりやすいと思うため論理演算子でもビット演算子のどちらが初心者向きかというよりも自分が分かりやすい方を使うのがベターtruefalseってよく分からないという人が無理に論理演算子である&&||を使う必要はない)だと思います。(条件判断がうまく行かないときは比較演算を省略しないということが重要)

《 補 足 》

※この部分は混乱するだけなので初心者(入門者)の人は読まなくてもいいです。
 逆に中級者(もしくはそれ以上)を自称する人はぜひ読んでください。

 プチコン3号には論理演算子である&&||が用意されているため「かつ」「または」を表現するのにわざわざビット演算子であるANDORを使う必要はないのですが、「BASICで論理演算子をサポートしているものはプチコン3号以外ほとんどない」「プチコン3号のヘルプでもIFにおいて複数の条件式を判定する際にANDORを使用している」「ANDORはヘルプで検索できるけど&&||をヘルプから検索できない」「ヘルプを見てない場合でも何も知らない人だと名称的に『かつ』『または』として使われがち」などの理由によって「IF〜THEN〜による条件判断」においてIF文を使って複数の条件式を判断する場合にANDORを使用する方法を紹介しました。
 とはいえ、ANDORを「かつ」「または」として使用するのは本来は正しい使い方とはいえないため上記のように正しく判定できる方法として&&||を解説しました。(ボタン入力判定のように普通にビット演算としてANDを使用している場合には&&を使う方が可読性が上がるというメリットもある)

 これが「配列変数」のところで出てきたVARDIMのように全く同じものであれば旧来のBASICとの互換性のためにDIMの説明を詳しく行わずともDIMの存在さえ書いておけば問題ないのですが、AND&&においては「同じ使い方もできる」というだけであって上記のように異なるものであり、さらにANDの初心者向けの解説として「ANDはボタン判定でのみ使う」とかいう中途半端なことを書いてしまうと例えば ボタンとは関係ないIF A==1 AND B==2 THEN C=3という条件式があったり、ボタンとは関係ないただのビット演算をしているときに「これは何かのボタンの判定を行っている」という誤った解釈をしてしまいます。
 したがって、プチコン3号においてANDORを「かつ」「または」として使えないとして紹介する、もしくは紹介そのものをしないという選択肢を採ると様々な問題点が生じてしまうというわけです。

 それでは、判定で躓いている初心者が&&||を使うとそれを理解できるようになるのかというとそんなことはなく比較演算子==!=<><=>=を省略しないということが非常に重要であると私は考えています。
 例えば、Aボタンが押されているかどうかを判定する場合はIF B AND 16 THEN 〜と記述(ここで変数BにはBUTTON()関数の値が入っているものとする)することが多いのですが、ANDがボタン入力判定に使われるという認識の人が多いため)B AND 16」を「B16の時(ボタン判定用)」と解釈している人も時々見られます。つまり、「==」を「AND」に置き換えることでボタン入力判定ができるということです。
 しかし、「==」を「AND」に置き換えられずはずがなくこれは明らかに間違いでB==16のように判定しているボタンが1つだけならばANDに置き換えてたまたま想定したように動いただけに過ぎません。

 これを「たまたま」ですまさないためにはビット演算の仕組みを理解しB AND 16016という値のみを取る」「値が0以外の時にtrueになる」というのを知っておく必要があります。これは上記で解説しているため本ページに書かれていることをちゃんと理解していれば全く問題ありません。
 本ページで書かれていることで分からない部分がある、もしくは、そもそも本ページの存在さえ知らないという初心者の人はIF (B AND 16)==16 THEN 〜のように比較演算「== 16」を省略せずに記述することで「B AND 16の値が16の時にTHEN以下を実行する」というのが誰でも分かるようになり、間違うことも無くなるということです。(その際はビット演算子であるANDの動作の仕組みを完全に理解しておかなくてはならないということはなく上記のイメージ図のようにブラックボックス状態でも問題はない)
 つまり、IF B AND 16 THEN 〜というのはIF (B AND 16)==16 THEN 〜から==16を省略したものとして考えることが初心者にとっては理解しやすいということです。(このように考えておけばどのような場合に省略できるのかを知らずに省略して正しい動作が期待できるわけがないということも分かる)

 条件式が1つでも「B AND 16」が「B16の時(ボタン判定用)」と考えている状態の人だと複数の条件を記述する際に「かつ」をANDで記述するのか&&で記述するのかは些細な問題といえます。
 例えば、フラグを示す変数F0の時にAボタンを押したらTHEN以下を実行するというプログラムを作る場合に IF F==0 AND (B AND 16)THEN 〜 のようにANDを「かつ」として使うと正しく動作できません。しかし、この場合も比較演算を省略せず IF F==0 AND (B AND 16)==16 THEN 〜 と記述すれば正しく動作はできます。
 確かにANDを使わず&&を使って IF F==0 && (B AND 16)THEN 〜 のように記述すれば正しく動作するのですが「B16の時(ボタン判定用)」という考えのままだとその場しのぎになってしまい得策とは言えません。

 したがって、よりスムーズな理解を行い自然に中級者へとなれるように当サイトの講座では初心者の人へは「条件式は比較演算を省略せずに書く」ということを強く勧めています。そして、(その際はANDを「かつ」として使用するのは間違いではないため)、「ANDOR」よりも「&&||」の方がベターであるという程度に論理演算子の方を勧めています。(決して「かつ」を表現するのにANDを勧めているわけではない)
 これによって、下記のような流れが非常にスムーズに理解できるようになります。

 IF B==16 THEN 〜Aボタンが押されているかが判定できる
     ↓
 IF B==48 THEN 〜ABボタンが両方押されているかが判定できる
     ↓
 IF (B AND 16)==16 THEN 〜 で他のボタンに影響されずAボタンが押されているかが判定できる
     ↓
 IF (B AND 48)==48 THEN 〜 で他のボタンに影響されずABボタンが両方押されているかが判定できる
     ↓
 IF (B AND 48)==16 THEN 〜 のような書き方が可能なことを知ることで更なる知識の深まりが出てここでようやく比較演算を省略した場合の問題点も分かるようになる。
  ※すべて変数BBUTTON()関数の値が入っている場合

 これが、いきなり IF B AND 16 THEN 〜と書いてしまうとIF B==16 THEN 〜との繋がりがない上に見た目が似ているため逆に理解しにくくなったり間違えた理解をしてしまいます。
 IF B AND 16 THEN 〜はあくまでIF (B AND 16)==16 THEN 〜から比較演算である「==16」を省略したものです。なぜ省略できるのかを初心者に分かる形で説明しないと中途半端な理解なままで終わってしまい今は良くても今後は知らずに誤動作をするコードを書いてしまう恐れがあり、中級者への道が遠ざかってしまいます。
 それから、「かつ」は&&を使えばIF (B AND 48)==16 THEN 〜IF B AND 16 && !(B AND 32) THEN 〜で簡単に記述できるし、IF (B AND 48)==48 THEN 〜IF B AND 16 && B AND 32 THEN 〜で簡単に記述できそこからの発展性はありますが、IF B==48 THEN 〜からIF (B AND 48)==48 THEN 〜は流れがスムーズなのに対してIF B==48 THEN 〜からIF B AND 16 && B AND 32 THEN 〜は流れが完全に途切れていて流れのスムーズさを重視するためにはIF B==16 THEN 〜IF B AND 16 THEN 〜に発展させたのならば)IF B==16 && B==32 THEN 〜の存在から発展させる必要があります。しかし、IF B==16 && B==32 THEN 〜は明らかに誤っているコードでありそこから発展させるのは困難です。
 したがって、比較演算を省略しないということが初心者にとっては最もスムーズな理解へと繋がると私は考えています。とはいえ、ANDによる複数条件式の判断を覚える前に&&を使ってはダメということではなく本講座においてあえて先にANDを書いているのは「便利なものの便利さは不便なものを先に使った方が分かりやすい」という程度と思って下さい。(実際にMiiverse上で「ANDで複数条件の判断を行うのは間違い」という考えを持つ人がいたけど「&&が正しいやりかた」と先に覚えてしまうとそのような偏見的な考え方になってしまう恐れがある)



RETURN (プチコン3号講座のページにもどる) RETURN *MAIN (トップページにもどる)

inserted by FC2 system