スケジュール前のページJavaの基礎3

JAVAの基礎4

同じ処理を何度も繰り返して実行したい時に,その部分に「反復構造」を用いると処理を一度だけ記述するだけで済みます.

反復構造1:WHILE文

「WHILE文」と言う反復構造について説明します.

WHILE文の構造

「WHILE文」の基本的な構造は次のようなものです.「while(条件式)」において,各反復の最初にここの条件式が判定され,この条件式が「真」のときだけ反復が実行されます.

初期設定
while(条件式){
	繰り返す処理
	再初期化
}

1からxまでの和を求めるプログラムを作ってみましょう.

プログラムの構造は,次のようになります.


while flow

各段階での変数の中身を見てみましょう.

例えば,5を入力したとします( x = 5 となる).

jix
初期化015
ループ部分:(while の中身)
ループ回数(iの値)j=j+i内容i++(再初期化)条件判定(i < = x)
11=0+11=0+1i++ = 22 < = 5 : true
23=1+23=(0+1)+2i++ = 33 < = 5 : true
36=3+36=(0+1+2)+3i++ = 44 < = 5 : true
410=6+410=(0+1+2+3)+4i++ = 55 < = 5 : true
515=10+515=(0+1+2+3+4)+5i++ = 66 < = 5 : false
終了時
1515 : 5までの和6

以上のように,i を1づつ増やしながら計算させ,while の条件を i<=x とすれば,入力した回数だけ繰り返し計算することになる.その結果,最終的に j に入力した数値の和が入ることになる.


具体的には次のように書きます.

/**************************************************
        反復構造:while文
**************************************************/
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;

public class FirstREP extends Application{
	
    public static void main(String[] args) {
        launch(args);
    }
    
    TextField tf1 = new TextField();
	Label label1 = new Label("整数を入力して下さい");
	Label label2 = new Label();
 
    @Override
    public void start(Stage stage) throws Exception {
    	
    	stage.setTitle("Application FirstREP");
    	
    	VBox root = new VBox();
    	
    	root.setAlignment(Pos.CENTER);
    	root.setPadding(new Insets(10,10,10,10));
    	root.setSpacing(10.0);
    	
    	HBox pane1 = new HBox();
    	
    	pane1.setAlignment(Pos.CENTER);
    	pane1.setPadding(new Insets(10,10,10,10));
    	pane1.setSpacing(5.0);
    	
    	tf1.setAlignment(Pos.CENTER_RIGHT);
    	tf1.setMaxWidth(50);

    	pane1.getChildren().addAll(label1,tf1);
    	
    	tf1.setOnAction(event -> calcValue());
    	
    	root.getChildren().addAll(pane1,label2);
    	
    	Scene scene = new Scene(root,400,200);
    	stage.setScene(scene);
        stage.show();
    }
    
    private void calcValue() {
    	String s = tf1.getText();
    	int x = Integer.parseInt(s);

    	//while文
    	//初期化
    	int i = 1;
    	int j = 0;
    	
    	while(i <= x){			// i <= x が条件式
    	
    		j = j+i;		//繰り返す処理
    		
    		i++;			//再初期化 ( i = i + 1 と書いても同じ)
    	
    	}
    	
    	label2.setText( x + "までの和は" + j + "です.");
    	
    }
 
}

練習問題7‐1

上のプログラムを参考にして,次のどれかのプログラムを作って実行してみましょう.

  1. 与えた数 x までの階乗を求めるプログラム.クラス名は「Ex07_1a」とせよ.

    データ型が int の場合 12 の階乗までしか正しく計算できません.より大きな階乗を求めたい場合は,long型を使用します.

  2. 与えた数 x までの1つ置きの和と積(1+3+5+…とか,2*4*6*…のような)を求めるプログラム.クラス名は「Ex07_1b」とせよ.

    ヒント:例題は1から始めて増やしながら計算をしているが,この問題は,増やしながら計算すると偶数の時うまくいかない(何故かは考えて見てください.)ので入力した値から減らしながら計算させる.

  3. 入力した数 x に対して,フィボナッチ数列の x 項目を求めるプログラム.クラス名は「Ex07_1c」とせよ.

    フィボナッチ数列は,最初の2項をそれぞれ\(F_0 = 0\),\(F_1 = 1\)として,それ以降の項は,\(F_{n+2} = F_{n} + F_{n+1}\)の漸化式で決まる数列です.


反復構造2:DO-WHILE文

この書き方は,ほとんど「WHILE文」と同じですが,反復の終了の判定を繰り返し部分の最後に行います.したがって,少なくとも一回は処理が実行されます.

DO-WHILE文の構造

「DO-WHILE文」の基本的構造は以下の通りです.

初期設定
do{
	繰り返す処理
	再初期化
}while(条件式);

ax = b の解を1000分の1の正しさで求めるプログラムを作ってみましょう.

方程式の解は,\( y = -ax+b \) を計算したときに,\(y\) が0になる \(x\) です.単純なプログラムでは人間のように式変形によって解を求めることはできません.したがって,プログラムでは,\(y\) の値が最も0に近くなる \(x\) を探す方法を取ります.
具体的には,\(x\)の初期値を(例えば0に)設定し,式に代入して\(y\)の値を計算し,それが0より大きければ \(x\) を求めたい正しさの値 \(\Delta x\) だけ増やして再度 \(y\) の値を計算するという作業を繰り返し実行するようにして,\(y\) の値が負になったときの \(x\) の値が方程式の解の近似値であると考えます.

x+Δx x x(solution) x y

プログラムの構造は,次のようになります.


do-while flow

2つの数(浮動小数)を受け取って解を表示するプログラムにします.入力は,例えば a が 3.b が 4 の場合,最初の入力欄に 3.0,次の入力欄に 4.0 のように作ります.また,答えを表示する時に,小数点以下が3桁まで表示するようにします.

具体的には以下のようになります.x の値を初期値0から1000分の1ずつ増やしていって,y の符号が変わった所で終了させます.この時の x の値が方程式を満たす数値に一番近いはずです.

/**************************************************
        反復構造:do-while文
**************************************************/
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import java.text.DecimalFormat;

public class SecondREP extends Application{
	
    public static void main(String[] args) {
        launch(args);
    }
    
    TextField tf1 = new TextField();
    TextField tf2 = new TextField();
	Label label1 = new Label("a,bを入力して下さい:ax = b");
	Label label2 = new Label("a = ");
	Label label3 = new Label("b = ");
	Label label4 = new Label();
	
    @Override
    public void start(Stage stage) throws Exception {
    	
    	stage.setTitle("Application SecondREP");
    	
    	VBox root = new VBox();
    	
    	root.setAlignment(Pos.CENTER);
    	root.setPadding(new Insets(10,10,10,10));
    	root.setSpacing(10.0);
    	
    	HBox pane1 = new HBox();
    	
    	pane1.setAlignment(Pos.CENTER);
    	pane1.setPadding(new Insets(10,10,10,10));
    	pane1.setSpacing(5.0);
    	
    	HBox pane2 = new HBox();
    	
    	pane2.setAlignment(Pos.CENTER);
    	pane2.setPadding(new Insets(10,10,10,10));
    	pane2.setSpacing(5.0);
    	
    	tf1.setAlignment(Pos.CENTER_RIGHT);
    	tf1.setMaxWidth(50);
    	
    	tf2.setAlignment(Pos.CENTER_RIGHT);
    	tf2.setMaxWidth(50);

    	pane1.getChildren().addAll(label1);
    	pane2.getChildren().addAll(label2,tf1,label3,tf2);
    	
    	tf1.setOnAction(event -> findSol());
    	tf2.setOnAction(event -> findSol());
    	
    	root.getChildren().addAll(pane1,pane2,label4);
    	
    	Scene scene = new Scene(root,400,200);
    	stage.setScene(scene);
        stage.show();
    }
    
    private void findSol() {
    	String s1 = tf1.getText();
    	double a = Double.parseDouble(s1);
    	String s2 = tf2.getText();
    	double b = Double.parseDouble(s2);
    	
    	/********* DO-WHILE文 ************************************/
    	
    	double y;
    	double x = 0.0;			//初期設定
    	
    	do{
    		y = - a*x + b;				//繰り返す処理
    		x = x + 0.001;			//再初期化
	}while(y > 0);		// y < 0 が条件式
    	
    	x = x - 0.0015;		// 1つ前と2つ前の x との間に解がある筈 
		
	//数値の書式を作成(小数点以下3桁を表示)
	DecimalFormat df = new DecimalFormat(".000");
	
	//数値に書式 df を設定して表示
	label4.setText( a + "x = " + b + "の解は,x = " + df.format(x) + "です."); 	
   	
    }
 

}


練習問題7‐2

上のプログラムを参考にして, 次のどれかのプログラムを作成して実行してみましょう.

  1. \(y = ax + b\) と \(y = kx\) の交点を1000分の1の精度で求めるプログラムを作ってみましょう.ただし,\( a < 0,\ b > 0,\ k > 0 \) で考える.クラス名は「Ex07_2a」とせよ.
  2. \(y = ax + b\) と \(y = cx + d\) の交点を1000分の1の精度で求めるプログラムを作ってみましょう.ただし,\( a < 0,\ b > 0,\ c > 0,\ d < 0 \) で考えてください.クラス名は「Ex07_2b」とせよ.
  3. \(y = x^2 + ax + b\) と \(y = kx\) の交点を1000分の1の精度で求めるプログラムを作ってみましょう.クラス名は「Ex07_2c」とせよ.
    注意:
    1. xの2乗はプログラム中では x*x と書く.
    2. 入力する a, b,k の値に気をつける(ヒント:判別式 > 0).解がない場合,繰り返しが止まらなくなるので注意.
      (プログラムが止まらなくなった時は,ターミナルでキーボードのコントロールキーを押しながらcを押す.)
    3. 初期値は,二次関数の頂点の位置から始めるのが良い.なぜかは考えてみましょう.
    4. 解は2つあります.

スケジュール前のページJavaの基礎3