今回から数回にわたって、前回 までとはうって変わって新しいことを学びます。それは論理の数学です。「 論理?高校数学の教科書には出てこなかったよ!」大丈夫、ご心配なく。高校で学んだ数学の方がよっぽど難しいんです。論理の数学はとってもシンプルです。
なぜ論理の数学を学ぶのでしょうか。それはプログラムの動きをコントロールするために必要不可欠だからです。論理が適切に組み立てられていなければ、プログラムは目的通りに動きません。論理の数学はプログラマの必須技術です。
更に、論理の数学をしっかり身につけると、プログラムをシンプルでコンパクトに、そして高速にできます。例えて言えば、論理に関する知識・技術を知ったプログラマは、大工としてひとつの作品がなんとか作れるようになった、という段階に当たるかもしれません。論理の数学を自在に使いこなすプログラマは、無駄を省いてシンプルかつエレガントな仕事をする名人大工に例えられます。
とりあえず動くプログラムを作ることが出来るという段階から、シンプルかつエレガントなプログラムを作ることが出来るプログラマへ、今回から始まる論理に関する学習でステップアップしましょう。
図14.1 Simple is Best !
論理とは
論理 とは、ある条件が正しいか、正しくないか、成り立つか、成り立たないかということを取り扱うものです。
正しいとか、成り立つといったことを、論理の言葉で真 (しん)といい、正しくないとか成り立たないといったことを偽 (ぎ)といいます。真や偽といった値のことを論理値 といいます。ブール値と呼ぶ流儀もありますが、論理値の方が直感的でわかりやすいと思いますので、この連載では論理値という呼び名を用います。Java言語で論理値を格納する型はboolean型 (「 ブーリアンがた」と読みます)です。こちらはJava言語の変数の型として一般的になっている名称なので、論理型と呼び換えず、そのまま用います。boolean型ではtrueが真を表し、falseが偽を表します。
プログラムの実行中には変数の値が様々に変化します。変数の値の変化に応じて条件式の論理値が変化します。この論理値の値に応じた処理をプログラムに書き表します。プログラマの仕事は、このような作業の積み上げです。
数の大小とか、文字列の等しい・等しくないといった条件を表した文章のことを命題 といいます。命題とは、意味に不明なところのない文章です。命題には成り立つものと成り立たないものがあります。命題は真か偽の論理値を持つのです。
プログラムで命題を取り扱う場合には、式の形で書き表します。そのようなものを条件式 といいます。例えば次のように命題を条件式に書き換えることが出来ます。
命題「iは0より大きな数である。」
条件式 i > 0
例えば、int型変数iの値が1のとき、i > 0という条件式の演算結果はtrue、i < 0やi == 0という条件式の演算結果はfalseになります。
条件式には比較演算子(連載第3回 で紹介しました)の他に、論理の働きを持たせた論理演算子 を用います。論理演算子を用いた条件式のことを論理式 ともいいます。例えば次のような命題は論理演算子を含む条件式、すなわち論理式に書き換えることが出来ます。
命題「iもjも0より大きな数である。」
条件式(論理式) ( i > 0)&(j > 0)
&というJava言語の論理演算子は「AかつB」の「かつ」を表す論理記号です。「 かつ」とは「両方とも」という意味で、アンドと読みます。このような論理記号については次回以降でじっくりと学習しますので、ここでは紹介する程度の説明にとどめます。
論理式は一般の計算式とは異なる計算法則を使って変形できます。論理式を変形するための公式や法則をまとめて論理代数 といいます。
プログラミング言語には、命題とその真偽に応じた処理を記述するための命令があります。それらを条件判断文 と言います。ですから、論理の数学をきちんと使えるようになって初めて、条件判断文の能力を十分に活用できるようになるのです。
論理をプログラムの改善に活用した例
具体的な例を紹介しましょう。これから紹介するのは「ふたつの論理値が両方真かどうかを確認する」プログラムです。細かな部分はさておいて、次の二つのソースコードを比較してください。
その1
01: //filename : TestBoolean.java
02: class TestBoolean {
03: public static void main(String[] args) {
04: boolean a = true; boolean b = false;
05: if (a){
06: if (b){
07: System.out.println("aもbも真でした。" );
08: } else {
09: System.out.println("両方真ではありませんでした。" );
10: }
11: } else {
12: System.out.println("両方真ではありませんでした。" );
13: }
14: } // end of main
15: } // end of class
その2
01: //filename : TestBoolean2.java
02: class TestBoolean2 {
03: public static void main(String[] args) {
04: boolean a = true; boolean b = false;
05: if (a && b){
06: System.out.println("aもbも真でした。" );
07: } else {
08: System.out.println("両方真ではありませんでした。" );
09: }
10: } // end of main
11: } // end of class
どちらも「ふたつの論理値が両方真かどうかを確認する」という同じ働きのプログラムです。しかし「その2」のプログラムは論理の数学を活用して短くシンプルになっています。論理の数学を知っていると、こんなふうにソースコードを改善することができるのです(※ ) 。シンプルなコードは読み間違いも起こしにくくなります。
このような単純な場合でさえ、問題を正確に理解し、条件式や条件判断文を正しい論理で組み立てられなければ、正しく動くプログラムは作られません。文章の読解力に加えて、論理の数学の力が必要なのです。
さあ、プログラミングに役立つ論理の数学の学習がスタートします。論理の数学でプログラムを正しく作り、整理し、適切な簡略化と処理の高速化を図るスキルを身につけ、ステップアップしましょう。
コラム 論理代数とハードウエア技術者
論理代数は、論理回路を組むハードウエア技術者にとって特に重要な技術です。ハードウェア技術者はIC(集積回路)チップを上手につないで目的の仕事をする回路を作ります。小規模な回路であれば、できるだけ同じ種類のICチップだけで、なるべく少ないチップ数で回路を組むようにします。大規模な回路ならば、消費電力や実装面積の節約のため極力小さな回路になるようにします。そのようなことは、論理代数があるからこそ可能なのです。
私自身は論理代数を論理回路に関する学習の中で身につけました。論理代数はパズルのようで楽しく、紙いっぱいに広がっていた論理回路がシンプルに変形できたときなどはうれしくて手をたたいたものでした。
後にプログラミングの世界に没頭していったとき、複雑でとても理解できないと思っていた他人のプログラムを、論理代数を活用してシンプルに書き直せたときには我ながら驚きました。
論理代数はハードウエア技術者にとっても、ソフトウエアプログラマにとっても有益な、必須の技術なのです。知らないと、損ですよ。
今回のまとめ
論理は正しく動くプログラム作りに必要です。
論理代数はソースコードの簡略化、高速化、保守性の向上に役立ちます。