31.6 関数の定義

2次方程式 “x2+2x+1=0” の解を計算させてみましょう.一般に,2 次方程式 “ax2+bx+c=0” の解は “(-b±√(b2-4ac))/2a” なので,解の 1 つは

// Program.java: 解の公式 class Program { public static void main(String[] args) { System.out.println((-2 + Math.sqrt(2 * 2 - 4 * 1 * 1)) / (2 * 1)); } }
-1.0
のように求めることができます.ここで “Math.sqrt” はhwb31.4 関数の利用で出てきた平方根を求めるメソッドです.これが小数を返すため,式部分の全体の値も小数になっています.

同様にして,“5x2+7x-4=0” であれば,

System.out.println((-7 + Math.sqrt(7 * 7 + 4 * 5 * 4)) / (2 * 5));

0.43578166916005473
という具合です.

しかし,似たような長い式を何度も書くのは面倒ですし,間違いも起こしがちです.そこで a, b, c が与えられたら2次方程式 “ax2+bx+c=0” の解を 1 つ “(-b+√(b2-4ac))/2a” を求める計算式に “quadratic1” という名前を付けてみましょう.

つまり,関数を自分で作成することになります.このように似たような処理を関数として定義して,それを何度も使うことで作業の量を減らすことができるのがプログラミングの利点の一つです.

関数の定義

Java で関数,つまりメソッドを作成し名前を付ける場合には,

戻り値の種類 メソッド名(引数1の種類 引数名1, 引数2の種類 引数名2, ...) {
  処理;
  return 戻り値;
}

のように書きます.このメソッドは処理を行って,“return” のところで計算した値を戻り値として返します.

今回の “quadratic1” の場合は,引数を小数として取るとして,次のようになります.

double quadratic1(double a, double b, double c) {
  return (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
}

これで Java に “quadratic1” という名前のメソッドとその処理を覚えさせることができます.

ただし,実際にプログラムでメソッドを作るにはさらに注意点があります.

1つ目はメソッドを書く位置です.今まで処理は “main” という,これもメソッドなのですが,その中に書いていました.しかし,メソッドの定義は “main” の中ではなく “main” と並列させる形で書くことになっています.つまり,“Program” よりは内側ですが,“main” の外にメソッドの定義は書いてください.

次に飾り言葉です.上の形で作ったメソッドは利用するのに特殊な手順を踏む必要があります.それを回避するために “main” と同様に “static” を付けてください.“public” は今は関係なく,なくてもよいのですがせっかくなので付けておきます.

以上によって,ソースコードの構成は次のようになります.

// Program.java: 解の公式 class Program { public static double quadratic1(double a, double b, double c) { return (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a); } public static void main(String[] args) { } }

なお,メソッドでも “System.out.println” などの処理だけ行って戻り値はないという場合があると思います.その場合は

void メソッド名(引数1の種類 引数名1, 引数2の種類 引数名2, ...) {
  処理;
}

と書きます.

実際に “main” はこの方法で作られたメソッドで,プログラムを “java Program” で実行すると,“Program” の中にあるメソッド “main” が呼び出されてそこに書かれた処理を順番に行っています.

定義した関数の利用

それでは,関数として定義した解の公式を使って,“x2+2x+1=0” の解を求めてみましょう.

hwb31.4 関数の利用にある通り,メソッドを使う場合には,

メソッド名(引数1, 引数2, ...)

のように書きます.

// Program.java : 解の公式 class Program { public static double quadratic1(double a, double b, double c) { return (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a); } public static void main(String[] args) { System.out.println(quadratic1(1, 2, 1)); } }
-1.0

メソッドを使うことで他の方程式の解を求める場合も簡単になりました.例えば “5x2+7x-4=0” の解を求めるのであれば次のように書き直すだけです.

System.out.println(quadratic1(5, 7, -4));
0.43578166916005473

2 次方程式の解の片方を求めるメソッド quadratic1 を定義したら,もう片方の解 “(-b-√(b2-4ac))/2a” を求める  quadratic2も定義してみましょう.

やり方としては,quadratic1 の定義の中の “+” を 1 ヶ所 “-” に書き換えるだけですから簡単そうです.しかしここでは,もう少し式を整理してから定義をやり直すことを考えます.

quadratic1 の定義をもう一度見てみましょう.

public static double quadratic1(double a, double b, double c) {
  return (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
}

まず,“b * b” という部分は “b” の自乗を計算しています.自乗を計算していることが読みとれるように,“square” というメソッドを定義して,それで置き換えてみましょう.

public static double square(double x) {
  return x * x;
}
public static double quadratic1(double a, double b, double c) {
  return (-b + Math.sqrt(square(b) - 4 * a * c)) / (2 * a);
}

このように,自分が定義したメソッド “square” を,別のメソッド “quadratic1” の定義に使うことができます.

さらに,“Math.sqrt’ ‘の内側の “square(b) – 4 * a * c” という部分は判別式と呼ばれています.ここも別に定義してみましょう.

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 quadratic1(double a, double b, double c) {
  return (-b + Math.sqrt(discriminant(a, b, c))) / (2 * a);
}

discriminant は二次方程式の各項の係数 a, b, c が与えられたら,その判別式 “b2-4ac” を求めるメソッドです.これを使った quadratic1 の定義は,前と比べてずいぶん簡単になりました.この定義でも,最初の定義と同じ結果になります.

さて,2 次方程式のもう片方の解の計算でした.判別式を計算するメソッドがすでにあるので次のように定義して使うことができます.

// 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 quadratic1(double a, double b, double c) { return (-b + Math.sqrt(discriminant(a, b, c))) / (2 * a); } public static double quadratic2(double a, double b, double c) { return (-b - Math.sqrt(discriminant(a, b, c))) / (2 * a); } public static void main(String[] args) { System.out.println(quadratic1(1, 2, 1)); System.out.println(quadratic2(1, 2, 1)); System.out.println(quadratic1(5, 7, -4)); System.out.println(quadratic2(5, 7, -4)); } }
-1.0 -1.0 0.43578166916005473 -1.8357816691600548

このように,何度も行う処理や何らかの意味のある部分はメソッドにするとよいです.