条件分岐

今回の内容

今回はコンピューターに簡単な「判断」を行わせるプログラムについて紹介します。前回までに紹介した内容は、主に入力された値を加工して、出力するだけのものでした。そのため、次のようなプログラムを書くのは非常に大変です。

図: 正解を入力する
図: 正解を入力した場合に表示されるメッセージ
図: 不正解を入力する
図: 不正解を入力した場合に表示されるメッセージ

なお、全てのコンピューターの処理は「順次」「分岐」「反復」という3つの構造の組合せで表現できるということが1966年の時点で証明されています。このうち「順次」とはこれまでに説明した「上から順番に実行していく」という形態のもので、今回紹介するものは「分岐」という条件によって枝分かれする処理に関するものです。最後の「反復」については授業全体の半分くらいのところで紹介する予定です。

図: 構造化定理

今回の授業で、コンピューターが判断を下しているようなプログラムを書けるようになりますので、先ほど紹介した簡単なクイズを作成してみましょう。

今回の作業

今回の例題、練習問題、課題は以下のパッケージに作成してください。

パッケージの名前
j1.lesson03

クラスの作成方法については、「クラスを作成する」を参照してください。

条件分岐

入力された値によって処理を変える

先ほど紹介したプログラムをしっかり読んでみましょう。

リスト: MathQuiz
package j1.lesson03;

import javax.swing.JOptionPane;

public class MathQuiz {

    public static void main(String[] args) {
        new MathQuiz().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("10 + 20 = ?");
        int answer = Integer.parseInt(input);
        if (answer == 30) {
            JOptionPane.showMessageDialog(null, "正解です");
        }
        else {
            JOptionPane.showMessageDialog(null, "不正解です");
        }
    }
}

ここには、ifやelseなどの見慣れないものと、「正解です」「不正解です」などのダイアログを表示するこれまで同様のプログラムの断片が含まれています。

リスト: MathQuiz(抜粋)
if (answer == 30) {
    JOptionPane.showMessageDialog(null, "正解です");
}
else {
    JOptionPane.showMessageDialog(null, "不正解です");
}

最初に見てほしいのは、前半の「if (answer == 30) { … }」という部分です。このifは英語のifと同じで、「もし~であったら」ということを表しています。

ifの直後に出現する「(answer == 30)」の部分は、先ほどのifの「条件」を表しています。この == は + や – などと同様に演算子で、「同じ値かどうか」という「そうである」または「そうでない」 で答えられることについて調べます。つまり、「(answer == 30)」という条件は「answerに記憶させた値と、整数の30が同じ値であるかどうか」ということについて計算し、answerに記憶させた整数が30であれば「そうである」、それ以外では「そうでない」という結果になります。

さらにそのあとに出現する「{ … }」の部分には、「正解です」と表示するための命令が書いてあります。つまり、先ほどの「(answer == 30)」という条件が成立する場合に処理される内容です。

対して、残りの「else { … }」の部分には、「不正解です」と表示するための命令が書いてあります。これは先ほどと逆で、「(answer == 30)」という条件が成立しない場合に処理される内容です。なお、これは英語のelseと同じで、「そうでなければ」ということを表しています。

このような「条件によって動きを変える」ものを「if文」と呼びます。まとめると、if文は次のように書けます。これは「もし~であったら」と「そうでなければ」という意味になりますので、条件をコンピューターに判断させて、その結果によって別々の処理を行うことができます。

if (<比較される値> == <比較する値> ) {
    <成立する場合の命令>
}
else {
    <成立しない場合の命令>
}

このような流れは「フローチャート」というものでも表現できます。

図: if文の処理の流れ

練習: 別のクイズ

作成するクラスの名前
MathQuizAlt

例 (MathQuiz) と別のクイズを作成しなさい。

比較の種類

もう少し複雑な判断についても考えてみましょう。次のプログラムの動作を予測し、実際に実行して確認してみて下さい。

リスト: PassFail
package j1.lesson03;

import javax.swing.JOptionPane;

public class PassFail {

    public static void main(String[] args) {
        new PassFail().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("得点を入力");
        int score = Integer.parseInt(input);
        if (score < 60) {
            JOptionPane.showMessageDialog(null, "不合格です");
        }
        else {
            JOptionPane.showMessageDialog(null, "合格です");
        }
    }
}

今回のプログラムでは、ifの条件の部分に新しい演算子を使っています。

リスト: PassFail(抜粋)
if (score < 60) {
    JOptionPane.showMessageDialog(null, "不合格です");
}
else {
    JOptionPane.showMessageDialog(null, "合格です");
}

この < は「より小さい」という不等号を表す演算子で、「(score < 60)」は「scoreに記憶させた値が60より小さい」という条件を表しています。この条件が成立する場合には「不合格です」と表示し、成立しない場合、つまり「scoreに記憶させた値が60以上」の場合には「合格です」と表示します。

これまでに紹介した条件に関する演算子は、==, < の2つですが、これ以外にもいくつか存在します。

Javaでの書き方 数学での書き方 意味
a == b a = b aはbと等しい
a != b a ≠ b aはbと等しくない
a < b a < b aはbより小さい
a > b a > b aはbより大きい
a <= b a ≦ b aはbより小さいか、等しい (以下)
a >= b a ≧ b aはbより大きいか、等しい (以上)

上記はいずれも == の代わりに利用できますので、if文の形式は次のようになります。

if (<比較される値> <演算子> <比較する値>) {
    <成立する場合の命令>
}
else {
    <成立しない場合の命令>
}

練習: 比較演算子

作成するクラスの名前
PassFailAlt

下記のプログラムを変更して、例 (PassFail) と同じ動作をするプログラムを書きなさい。ただし、「合格です」「不合格です」のメッセージの順序が先ほどと異なっていることに注意すること。

リスト: PassFailAlt
package j1.lesson03;

import javax.swing.JOptionPane;

public class PassFailAlt {

    public static void main(String[] args) {
        new PassFailAlt().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("得点を入力");
        int score = Integer.parseInt(input);
        if (________________) {
            JOptionPane.showMessageDialog(null, "合格です");
        }
        else {
            JOptionPane.showMessageDialog(null, "不合格です");
        }
    }
}

ブロック

次のプログラムはどのような動作をするでしょうか。

リスト: ShowAbsolute
package j1.lesson03;

import javax.swing.JOptionPane;

public class ShowAbsolute {

    public static void main(String[] args) {
        new ShowAbsolute().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("数値を入力");
        double number = Double.parseDouble(input);
        if (number < 0.0) {
            number = -number;
        }
        else {
            // この行は提示しない
        }
        JOptionPane.showMessageDialog(null, "絶対値は" + number);
    }
}

これまで と少し異なる点として、else { … }の部分に何も命令がありません。

リスト: ShowAbsolute(抜粋)
double number = Double.parseDouble(input);
if (number < 0.0) {
    number = -number;
}
else {
}

このように、ifやelseに続く { … }を「ブロック 」と呼びます。このブロックには命令を1つも書かなくてもいいですし、2つ以上の命令を書くこともできます。なお、このようにelseに続くブロックが空の場合には、elseそのものを省略できます。

リスト: ShowAbsolute(elseの省略)
double number = Double.parseDouble(input);
if (number < 0.0) {
    number = -number;
}

実際にelse { … }の部分を消して、正しく動作するか確認してみましょう。

複数に分岐する処理

少し複雑な動作をするプログラムを紹介します。

リスト: SelectQuiz2
package j1.lesson03;

import javax.swing.JOptionPane;

public class SelectQuiz2 {

    public static void main(String[] args) {
        new SelectQuiz2().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("条件分岐をするには?\n"
            + "(1) if文\n"
            + "(2) for文\n");
        int answer = Integer.parseInt(input);
        if (answer == 1) {
            JOptionPane.showMessageDialog(null, "正解です");
        }
        else if (answer == 2) {
            JOptionPane.showMessageDialog(null, "不正解です");
        }
        else {
            JOptionPane.showMessageDialog(null, "無効な値です");
        }
    }
}

これまでの分岐は「if … else …」のように「2つのうちどちらか」という形の分岐でしたが、今回は3つ以上に分岐しています。

リスト: SelectQuiz2(抜粋)
if (answer == 1) {
    JOptionPane.showMessageDialog(null, "正解です");
}
else if (answer == 2) {
    JOptionPane.showMessageDialog(null, "不正解です");
}
else {
    JOptionPane.showMessageDialog(null, "無効な値です");
}

このプログラムを実行して、1を入力すると「正解です」、2を入力すると「不正解です」、それ以外の整数を入力すると「無効な値です」と表示されます。

次のように変形するとわかりやすいかもしれません。

if (answer == 1) {
    JOptionPane.showMessageDialog(null, "正解です");
}
else
if (answer == 2) {
    JOptionPane.showMessageDialog(null, "不正解です");
}
else {
    JOptionPane.showMessageDialog(null, "無効な値です");
}

このように、elseに続くブロックの代わりに他のif文を置いた 形です。図で表すと次のようになります。

図: if-elseifの処理の流れ

このように、elseの直後に別のif文を連結させることで、「そうでなく、もし~のとき、」という処理を実現できます。これらを組み合わせることで、3つ以上の場合分けを表せます 。

if (<1つ目の条件>) {
    <1つ目の条件が成立する場合の命令>
}
else if (<2つ目の条件>) {
    <2つ目の条件が成立する場合の命令>
}
else if (<3つ目の条件>) {
    <3つ目の条件が成立する場合の命令>
}

else {
    <全ての条件が成立しない場合の命令>
}

練習: 3段階の成績表示

作成するクラスの名前
Grading

得点を整数で入力し、80点以上の場合は「すばらしい成績です」、そうでなく60点以上の場合は「合格です」、それ以外の場合は「不合格です」と表示するプログラムを作成しなさい。

複雑な条件

分岐については以上ですが、最後にif文で利用した条件についてもう少し詳しく紹介します。

リスト: InRange
package j1.lesson03;

import javax.swing.JOptionPane;

public class InRange {

    public static void main(String[] args) {
        new InRange().start();
    }

    void start() {
        String input = JOptionPane.showInputDialog("得点を入力");
        int score = Integer.parseInt(input);
        if (0 <= score && score <= 100) {
            JOptionPane.showMessageDialog(null, "正常な得点です");
        }
        else {
            JOptionPane.showMessageDialog(null, "異常な得点です");
        }
    }
}

これまで、条件の部分には2つの値とそれらを比較するための演算子を書いていましたが、今回のプログラムはもう少し複雑です。

リスト: InRange(抜粋)
if (0 <= score && score <= 100) {
    JOptionPane.showMessageDialog(null, "正常な得点です");
}
else {
    JOptionPane.showMessageDialog(null, "異常な得点です");
}

今回の条件は、2つの条件と新しい記号 && に分解できます。

図: 論理式の分解

この記号は「AかつB」 という接続詞 のようなものを表していて、例では「0 <= score」かつ「score <= 100」の場合にのみ条件が成立します。「0 <= score」と「score <= 100」の2つの条件が同時に成立すればいいので、最終的には「scoreが0以上100以下」という条件を表すことになります。

図: 論理積の数直線

このほかにも、|| という演算子を利用できます。これは「2つの条件のいずれかが成立する」というもので、「AまたはB」という条件 を表します。

図: 論理和の数直線

これまでに紹介した2つの値を演算子で比較する条件や、それらの条件を「または」「かつ」などで組み合わせた条件を、まとめて「条件式」と呼びます。新しく紹介した条件式の演算子は次の2つです。

Javaでの書き方 数学での書き方 意味
A && B A ∩ B AかつB
A || B A ∪ B AまたはB

練習: 3択問題

作成するクラスの名前
SelectQuiz3

整数を入力する3択のクイズを考え、入力した値によって「正解」「不正解」「無効な値」のいずれかを表示するプログラムを書きなさい。なお、else ifを利用して4つに分岐してもこのプログラムは書けるが、「または」という演算子を利用すること。

問題が思いつかない場合には、次のようなクイズを出題するプログラムを書くこと。

「以上」はどれ?
(1) ==
(2) <=
(3) >=

まとめ

全てのコンピュータの処理は「順次」「分岐」「反復」という構造の組合せで表せる、ということを紹介しましたが、今回はそのうち「分岐」について説明しました。Javaではif文を利用して条件ごとに別々の処理を行えます。

図: 構造化定理(再掲)

条件分岐

条件分岐は、次のようにif文を使います。

if (<条件式>) {
    <条件式が成立する場合の命令>
}
else {
    <条件式が成立しない場合の命令>
}
図: フローチャート(if-flow, 再掲)

このうち、{ … }となっている部分を「ブロック」と呼び、ブロックの中には複数の命令を書くことができます。3つ以上に分岐する場合には、elseに続くブロックの代わりに別のif文を書きます。

if (<1つ目の条件式>) {
    <1つ目の条件が成立する場合の命令>
}
else if (<2つ目の条件式>) {
    <2つ目の条件が成立する場合の命令>
}
else if (<3つ目の条件式>) {
    <3つ目の条件が成立する場合の命令>
}

else {
    <全ての条件が成立しない場合の命令>
}

なお、条件が成立しない場合の命令が不要であれば、else { … }全体を省略できます。

条件式

条件分岐に使う条件式には、まず次のような値の比較を紹介しました。

Javaでの書き方 数学での書き方 意味
a == b a = b aはbと等しい
a != b a ≠ b aはbと等しくない
a < b a < b aはbより小さい
a > b a > b aはbより大きい
a <= b a ≦ b aはbより小さいか、等しい (以下)
a >= b a ≧ b aはbより大きいか、等しい (以上)

他には、この条件式を組み合わせて複雑な条件式を表現する方法についても紹介しました。

Javaでの書き方 数学での書き方 意味
A && B A ∩ B AかつB
A || B A ∪ B AまたはB

以上が今回のまとめです。「コンピューターが判断を下し、場合によって行う処理を変える」というようなプログラムを書けるようになりました。