論理の数学は、これまでとは雰囲気が異なりまるでパズルのようです。取り扱うのは数値ではなく論理値ですし、加算や減算などの代わりに「かつ」「または」といった一見すると計算とは思えないコトバを使います。
なぜプログラマが論理の数学を学ぶ必要があるのでしょう。それは、論理の数学がプログラムの構造・動作を決定したり改善するのに役立つからです。
さて、ひとつのたとえを紹介します。優れた大工さんは優れた芸術家でもあります。美しく、無駄のない骨組み作りから仕事が始まります。その仕事ぶりは見るものを感動さえさせます。骨組みは、やがてコンクリや壁材の下になって見えなくなり、住む人にすばらしい姿が見えなくなります。しかし無駄なく適切に組み立てられた骨組みを持つ家は、風雪に耐え、長く強く存在し続けるでしょう。プログラマの仕事もこれとよく似ています。美しいソースコードは、コンパイルされてしまえばユーザの目に触れることはありません。しかし、無駄なく適切に作られたプログラムは、長くユーザに利便を与えて愛されることでしょう。プログラムの骨組みとは論理構造です。論理の数学は、理にかなって無駄がなく、美しいプログラムの骨組みをつくるために役立つのです。
今回は、しっかりと論理の数学の基本である、記号とその意味を学びましょう。
論理の数学の基本
論理記号
論理の数学で用いる記号には、いくつかの流儀があります。この連載では表15.1に示す論理記号を用います。論理和・論理積・論理否定が最も基本となる論理演算です。排他的論理和は3つの演算を用いて組み立てることができますから、最も基本となる論理演算とはいえません。しかし、特別に記号を作られるほどによく使われます。これら4つの記号と意味をしっかり覚えてください。
表15.1 論理記号一覧
名称(記号、読み) | 論理記号と論理式 | Java言語 | 式の意味 |
論理和(+、オア) | Z=A+B | z=a|b | AまたはBのどちらかが真ならZが真になる |
論理積(・、アンド) | Z=A・B | z=a&b | AとBのどちらも真のときZが真になる |
論理否定( ̄、ノット) | Z=Ā | z=!a | Aが偽のときZは真になる |
排他的論理和(⊕、エクスクルーシブ・オア) | Z=A⊕B | z=a^b | AかB一方のみが真のときZが真になる |
論理積の記号・は論理式中では省略することがあります。一般の数式で乗算を表す×を省略するのと同じです。例えばZ=A・Bという式は、Z=ABと書いても同じ意味です。式を誤解する余地がなければ積極的に省略します。ただし、Java言語のソースコード中で論理積演算子&を省略することはできません。
論理の数学では論理変数を大文字のアルファベット一文字で表すのが通例です。Java言語では変数は小文字で始めるのが通例です。表15.1はその通例に従っています。
ショートサーキット演算子
Java言語には効率のよい論理演算をするために表15.2に示すショートサーキット演算子があります。
表15.2 ショートサーキット演算子一覧
名称(読み) | 演算子の使用例 | 使用例の意味 |
ショートサーキット論理和(コンディショナル・オア) | z=a||b | aが真ならbの真偽は確認せずzに真を代入 |
ショートサーキット論理積(コンディショナル・アンド) | z=a&&b | aが偽ならbの真偽は確認せずにzに偽を代入 |
表15.2のショートサーキット論理和の使用例と意味の欄を見てください。z=a||bというプログラムが実行されたときに、boolean型変数aが真ならば、boolean型の変数bが真でも偽でも必ずzには真が代入されます。ショートサーキット論理和を用いていればJava言語はbの値を確認しないのです。この場合は実行の効率に大差がありません。しかし、もしbが大変実行時間のかかる「関数」であったら、「関数b」の実行を省くことができるショートサーキット論理和は有効です。
次の例を見てください。ショートサーキット論理積の有効な活用シーンです。
strはStringクラスのオブジェクトです。strにnullが入っているとき、str.equals("user")を実行してしまうとエラーが発生します。strにnullが入っているのは、strクラスのオブジェクトが作られていない時です。!=は「等しくない」という意味の比較演算子です。str!=nullの実行結果が真ということは、strクラスのオブジェクトが作られていますからstr.equals("user")を実行してもエラーにならないことが保証されます。このような場合にショートサーキット論理積を利用することで、きれいにコードが書けます。
ただし、次の場合にはショートサーキット演算子の使用が不適切です。
整数変数iの値がゼロ以下だと、次の++jが実行されません。条件式の中で値が変化するような場合で、両方の値の評価が必要ならば、ショートサーキット演算子の&&を用いず&を用いる必要があります[1]。常にどちらの演算子を用いるか、意識しておく必要があります。
真理値表
真理値表とは、論理式がどんな論理値をとるのか、全ての場合を列挙した一覧表です。真理値表は論理を表現するための、シンプルでわかりやすい方法です。
真理値表では論理値の真には1を、偽は0を用います[2]。
例えば、論理積A・Bの真理値表は表15.3のように書きます[3]。
真理値表には、考えられる全ての場合をもれなく列挙します。先ず、論理変数AとBの値がとりうる全ての組合せを作ります。真理値表では0と1で論理値を表現しますから、2進数にみたてて数え上げるようにすると、もれなく・ダブり無く表を作ることができます。そして、それに対応するように一番右側の列(縦の並び)に論理式A・Bの演算結果を書き込みます。
論理記号・はアンド、すなわち「~かつ~」を表しています。論理変数AとBが両方とも真でない限り、式全体の結果が真にならないという意味です。一番最後の行、AとBが両方とも真(1)のときだけA・Bの値が真になっています。確かにこの真理値表が意図する論理を表していることがわかります。
今回はここまで
論理演算子の意味をとらえることが出来ましたか?次回はそれぞれの論理記号について真理値表を書いてみましょう。そして、Java言語でboolean型と論理演算子を使ったプログラムを書いてみましょう。手を動かすと、読んでいるだけの時の倍以上理解できますよ。