31.8 条件分岐

2次方程式“ax2+bx+c=0” に対して解の個数を求める関数を作ってみましょう.ここまでで見てきたように,解を 0, 1, 2 個持つ場合の条件をそれぞれ式として書くことができていますので,あとは

  • 「解を 1 つも持たない」条件が成り立つならば “0”,
  • 「解を 1 つ持つ」条件が成り立つならば “1”,
  • 「解を 2 つ持つ」条件が成り立つならば “2”,

を返すような関数を作ればよいわけです.

このように,条件の真偽によって異なる処理をさせることを一般に条件分岐と言います.

条件分岐の方法

Java で条件分岐をしたい時は,

if(条件) {
  処理1
} else {
  処理2
}

または

条件 ? 式1 : 式2

のように書きます.この時,「条件」が成り立つ,つまり真偽値を計算して “true” だったら「処理1」または「式1」の計算が行われ,“false” だったら「処理2」または「式2」の計算が行われます.2 つの違いは,上の方が処理を行うのに対して,下では式の値を計算してそれが全体の結果になります.

簡単な利用例を少し見てみましょう.

System.out.println(1.3 >= 5.2 ? 1.3 : 5.2);
5.2
public static double max(double a, double b) {
  if(a >= b) {
    return a;
  } else {
    return b;
  }
}
public static void main(String[] args) {
  System.out.println(max(1.3, 5.2));
}
5.2
System.out.println(6 % 2 ? true : false);
Program.java:27: 互換性のない型 検出値 : int 期待値 : boolean System.out.println(6 % 2 ? true : false); ^ エラー 1 個 // 条件の部分は計算すると真偽値になるようにする必要がある

条件分岐ができるようになると,だいぶ計算できるものが増えます.

条件分岐の利用

条件分岐を使って,解の個数を求める関数 “number_of_roots” は次のように書くことができます.

public static int number_of_roots(double a, double b, double c) {
  if(no_roots(a, b, c)) {
    return 0;
  } else {
    if(one_root(a, b, c)) {
      return 1;
    } else {
      return 2;
    }
  }
}

少し複雑な式ですが,分解して考えればそれほど難しくありません.前から順に見てゆくと,

  • “if(no_roots(a, b, c)) { return 0; } else { … }” は「解を 1 つも持たないならば “0” を返す,そうでなければ“{ … }”」を表わします.
  • そして “{ … }” の部分の“if(one_root(a, b, c)) { return 1; } else { return 2; }”は「解を 1 つ持つならば “1” を返す,そうでなければ “2” を返す」を表わしています.

この 2 つを合わせると,次のようになります.

  • 「解を 1 つも持たない」ならば “0” を返す.
  • 「そうでない(解を 1 つか 2 つ持つ)」ならば,「『解を 1 つ持つ』ならば “1” を返す,『そうでない』ならば “2” を返す」.

つまり,

  • 「解を 1 つも持たない」ならば “0” を返す,
  • (解を 1 つか 2 つ持つときに)「解を 1 つ持つ」ならば “1” を返す,
  • (解を 1 つか 2 つ持つときに)「解を 1 つ持たない」ならば “2” を返す,

であるので,結局

  • 「解を 1 つも持たない」ならば “0” を返す,
  • 「解を 1 つ持つ」ならば “1” を返す,
  • 「解を 2 つ持つ」ならば “1” を返す,

ということになります.

なお,今回の例のように条件分岐した先で処理を 1 つしかしない場合や “else” の後で条件分岐をする場合は “{}” を省略することができます.つまり,次のように書いてもよいです.

public static int number_of_roots(double a, double b, double c) {
  if(no_roots(a, b, c)) return 0;
  else if(one_root(a, b, c)) return 1;
  else return 2;
}

しかし,“else if” はともかく,分岐の後の省略は処理を増やす時には結局 “{}” を足さなければならない上,忘れると別の動作になったりして不具合の元なので常に付けておくことを勧めます.

以上をふまえて,実際に計算させて正しく解の個数を求めているか調べてみましょう.

// Program.java: 解の個数 class Program { public static double square(double x) { return x * x; } public static double discriminant(double a, double b, double c) { return square(b) - 4 * a * c; } public static double eps = 0.000001; // 十分小さい数を用意 public static boolean two_roots(double a, double b, double c) { return discriminant(a, b, c) > eps; } public static boolean no_roots(double a, double b, double c) { return discriminant(a, b, c) < -eps; } public static boolean one_root(double a, double b, double c) { return !(two_roots(a, b, c)) && !(no_roots(a, b, c)); } public static int number_of_roots(double a, double b, double c) { if(no_roots(a, b, c)) { return 0; } else if(one_root(a, b, c)) { return 1; } else { return 2; } } public static void main(String[] args) { System.out.println(number_of_roots(1, -5, 6)); System.out.println(number_of_roots(1, 2, 1)); System.out.println(number_of_roots(1, 2, 2)); } }
2 1 0

良さそうですね.