次回の小テストでは、この課題の復習を行います。穴埋め問題も、単に穴埋めをするのではなく、理解して穴埋めをするようにして下さい。
<課題の前に>
- 課題全般に関するヒント:
- コンパイル時にエラーが出たら、まず、 「うまく動かないときのチェックポイント」 を参照して下さい。 9割方の問題はこれで解決するはずです。
- 文字をキーボードから入力する課題では「文字列を入力する方法(テンプレート)」のコードをコピー&ペーストして使ってOKです。
- 注意:ソースコードにインデントのないレポートは減点
- まず、このページの「1. インデント(字下げ)の基本【必読】」を読むこと。教科書p24,25も確認すること。
- 以下の課題では、提出するソースコードに、適切にインデントを付けること。 インデントをつけない レポートは減点、 再提出の対象とする。
【課題8】staticメソッド/復習課題
全履修者問題8-1~8-10を提出。ただし、8-5~8-10の「追加点課題」の提出は必須ではない。一通り終って余裕のある人はチャレンジしてみて下さい。
リンク先を一読してから課題に取り組むこと。
問題量は多いですが、課題全体はリンク先を読めば解ける簡単な問題か、または今までの復習問題で構成されています。
問題8-1 (メソッドとは)
「メソッドとは」を読み、次の問いに答えよ。
(問1) カギ括弧内の空欄(a)~(f)を以下に示したキーワードを使って埋め、対応する大文字の英字(A)~(F)でそれぞれ答えよ。解答には対応する英字だけで答えること。
プログラムの実行時には、いろいろなところで同じような処理を行うことがあります。 そのような処理を一つの機能としてまとめて、必要に応じて利用できるようにしておくと便利です。 これを実現するのが「 (a) 」です。 staticが付く「 (a) 」を「 (b) 」、付かないメソッドを「 (c) 」と呼びます。 戻り値の型voidというのは、「 (d) 」ことを意味します。 プログラムの実行時に最初に実行されるのは、あくまでも「 (e) 」。 「 (e) 」は特別なメソッドである。 「 (f) 」を実行しなくても、「 (a) 」の処理が最後の行まで到達すると、処理は呼び出し元に戻ります。
解答の選択肢
A:「return文」、B:「mainメソッド」、C:「戻り値を返さない」、D:「インスタンスメソッド」、E:「クラスメソッド」、F:「メソッド」
(問2) 「メソッドとは」の「MethodSample01.java」のソースコードを行番号付きで以下に示した。
以下に示した行番号1~7を使って、プログラムが実行される順序を示しなさい。
例:1→2→3→4→5→6→7
//MethodSample01.java /* メソッドの使い方を確認するサンプルクラス */ class MethodSample01 { // mainメソッドから呼び出すメソッド 1| static void hello(){ 2| System.out.println("こんにちは。"); 3| return; } 4| public static void main(String[] args) { 5| System.out.println("helloメソッドを呼び出します。"); 6| hello(); 7| System.out.println("helloメソッドを呼び出しました。"); } }※ この問題はコピペして実行しても解けません!「メソッドとは」を読んで下さい。
Hint:一番最初に実行されるのはmainメソッドです。helloメソッドはmainメソッドから呼ばれています。
問題8-2 (メソッドの引数)
「メソッドの引数」を読み、次の問いに答えよ。「メソッドの引数」のサンプルコード「MethodSample02.java」を以下に示した。
以下のソースコードが実行できるかどうかをまず確認してください。(コピペして良い)
その後、以下のソースコードを修正して、(自分の学籍番号下1桁 + 1)回だけ、自分の学籍番号を画面に出力させるプログラムを作って下さい。
ただし変えて良いのはmainメソッドの中身だけで、printMessageメソッドはそのまま使うこと。プログラム修正後のソースコードと実行結果を提出してください。
//MethodSample02.java /* メソッドの引数の役割への理解を確認するためのサンプルクラス */ class MethodSample02 { // 文字列msgを整数n回繰り返して出力するメソッド static void printMessage(String msg, int n){ for(int i = 0; i < n; i++){ System.out.println((i+1)+" "+msg); } } public static void main(String[] args) { //この課題で修正して良いのは、ここから下 printMessage("ゲームのやり過ぎに注意!", 4); printMessage("宿題は終わったかな。", 6); //この課題で修正して良いのは、ここから上まで } }学籍番号が201020505の場合、6回学籍番号を表示させるようプログラムを変更し、
1 201020505
2 201020505
3 201020505
4 201020505
5 201020505
6 201020505
と画面に出力されるようにします。
各自自分の学籍番号にあわせてプログラムを変更すること。
問題8-3 (メソッドの戻り値)
「メソッドの戻り値」を読み、次の問いに答えよ。「メソッドの戻り値」のサンプルコード「MethodSample05.java」を参考にして、以下のプログラム「Kadai8_3.java」における空欄「" (a) "」から「" (d) "」を埋めなさい。(ヒント:テキストP47「基本型」)
そうすることによりキーボードからの入力が偶数か否かを判定するプログラムを完成させよ。
プログラムのソースコードや実行例は提出せず、「" (a) "」から「" (d) "」の穴埋めに答えること。「" (d) "」ではisEvenメソッドを必ず使うこと。全てそれぞれ15字以内で記述すること。
//Kadai8_3.java import java.io.*; /* メソッドの戻り値への理解を確認するクラス */ class Kadai8_3 { // numが偶数か否かを判定するメソッド static 「" (a) "」 isEven(int num){ //「" (a) "」 if (num%2==0) return 「" (b) "」; //「" (b) "」; else return 「" (c) "」; //「" (c) "」; } public static void main(String[] args) throws IOException{ BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); System.out.println("正の整数を入力してください。"); int n = Integer.parseInt(br.readLine()); if(「" (d) "」) //「" (d) "」; System.out.println(n+"は偶数です。"); else System.out.println(n+"は偶数ではありません。"); } }
問題8-4 (変数の有効範囲)
「変数の有効範囲」を読み、次の問いに答えよ。次のカギ括弧内の空欄(a)~(g)を以下に示したキーワードを使って埋め、対応する大文字の英字(A)~(G)でそれぞれを答えよ。解答には対応する英字だけで答えること。
これまでの学習で使われてきた、メソッドの中で宣言される変数は、「 (a) 」と呼ばれます。 for文で宣言された変数も「 (a) 」です。 「 (a) 」は、それを宣言したブロックの中やfor文の中でのみ有効となります。 メソッドの「 (b) 」も「 (a) 」と同じ扱いとなり、メソッドの中でのみ有効です。 メソッドの中で宣言される「 (a) 」に対して、メソッドの外で宣言される変数を「 (c) 」と呼びます。 「 (c) 」の有効範囲は「 (d) 」です。 従って、「 (c) 」は複数のメソッドで共有できる変数と言えます。 staticが付く「 (c) 」を「 (e) 」、付かない「 (c) 」を「 (f) 」と呼びます。 「変数の有効範囲」の「ScopeSample02.java」のソースコードの一部を以下に示す。 これまで、mainメソッドの中に同じ変数名の変数を宣言した場合コンパイルエラーとなっていたはずであるが、 以下の「ScopeSample02.java」では、maxメソッドとminメソッドとで同じ名前の変数a,bを宣言し用いている。 これでもコンパイルエラーとならない理由は、2つのメソッドmaxとminの「 (b) 」a, bは、名前は同じでも「 (g) 」だから。
解答の選択肢
A:「別の変数」、B:「インスタンス変数」、C:「クラス変数」、D:「クラス全体」、E:「フィールド」、F:「仮引数」、G:「ローカル変数」
//ScopeSample02.java /* 変数の有効範囲への理解を確認するサンプルクラス */ class ScopeSample02 { //整数aとbを比較して大きい方を返す static int max(int a, int b){ return a > b ? a : b; } //整数aとbを比較して小さい方を返す static int min(int a, int b){ return a < b ? a : b; } }
問題8-5 (他のメソッドの呼び出し)
「他のメソッドの呼び出し」を読み、次の問いに答えよ。
(1) メソッドの中で別のメソッドを呼び出すことが出来る。これは正しいか。
(2) (追加点課題:余裕があれば解いてみてください)
攪乱順列<完全順列>を求めるメソッドkanjunを作って下さい。(攪 乱順列とは、1,2,3,・・・,nの数の札を並び替えたとき、先頭から数えた順番と札の番号が一致するものが1つもない並べ方のこと。)
- kanjunメソッドは、n個の攪乱順列の場合の数を戻り値とするメソッドとしてください。個数nを引数とすること。
- 「他のメソッドの呼び出し」にある「MethodSample07.java」の一部を以下に示す。この「MethodSample07.java」はコピペして使って良い。
- factorialメソッド、permutationメソッド、combinationメソッドの少なくとも一つをplura lpermメソッドで呼び出すこと。factorialメソッド、permutationメソッド、combinationメソッ ドの中身はいずれも変更してはならない。
ソースコードを提出せよ。実行結果はn=5のときを提出せよ。答えは44になる。何をしているのかわかるように、コメントを書くこと。
//MethodSample07.java /* 場合の数を計算するクラス */ class MethodSample07 { /*---- 階乗を求める ----*/ static int factorial(int n){ int factorial = 1; for(int i = 2; i <= n; i++){ factorial *= i; } return factorial; } /*---- 順列の総数を求める ----*/ static int permutation(int n, int r){ int p = factorial( n ) / factorial(n - r); return p; } /*---- 組合せの総数を求める ----*/ static int combination(int n, int r){ int c = permutation(n, r) / factorial(r); return c; } }
問題8-6 (配列を受け取るメソッド)
「配列を受け取るメソッド」を読み、次の問いに答えよ。
(1) 配列をメソッドの引数に指定することも出来る。これは正しいか。
(2) (追加点課題:余裕があれば解いてみてください)
「同じものを含む順列」問題を解く「pluralpermメソッド」を作りなさい。
(i) 「n 個のもののうち、a 個は同じもの、b 個は同じもの、c 個は同じもの、・・・を一列に並べたときの場合の数」を解くためのメソッドとする。
(ii) 問題8-5で示した「MethodSample07.java」をコピペして使って良い。factorialメソッド、permutationメソッド、combinationメソッドの少なくとも一つをpluralpermメソッドで呼び出すこと。
(iii) factorialメソッド、permutationメソッド、combinationメソッドの中身はいずれも変更してはならない。
ソースコードを提出せよ。実行結果では、a, a, b, b, c を一列に並べたときの場合の数を解いてください。答えは30になります。何をしているのかわかるように、コメントを書くこと。
Hint:引数にはint型配列を使い、戻り値にはint型変数を使うと良い。
問題8-7 (配列を返すメソッド)
「配列を返すメソッド」を読み、次の問いに答えよ。
(1) メソッドの戻り値に配列を指定することも出来る。これは正しいか。
(2) (追加点課題:余裕があれば解いてみてください)
受け取ったint型配列を小さい順にソートしてint型配列として返すメソッドを作ってください。ソートアルゴリズムは問わない。
たとえばint[] a={10,4,5};という配列aを引数として渡すと配列{4,5,10}が返ってくるようなメソッド。ソースコードと実行結果を提出。何をしているのかわかるように、コメントを書くこと。
問題8-8 (多次元配列の受け渡し)
「多次元配列の受け渡し」を読んで、次の問いに答えなさい。
(1) 多次元配列をメソッドの引数に指定することは出来る。これは正しいか。
(2) メソッドの戻り値に多次元配列を指定することは出来る。これは正しいか。
(3) (追加点課題:余裕があれば解いてみてください)
以下のメソッド(i)~(iv)を含むクラスを作りなさい。
(i) 行列の中身を表示するstaticメソッドを作りなさい。
(ii) 一つの行列Xと一つの定数kを引数として行列Xの定数k倍の行列Zを返すstaticメソッドを作りなさい。
(iii) 二つの行列X,Yを引数としてその和の行列Zを返すstaticメソッドを作りなさい。
(iv) 二つの行列X,Yを引数としてその積の行列Zを返すstaticメソッドを作りなさい。
ソースコードと実行結果を提出。ただし次の条件も満たすこと。
(v) 提出前にきちんと動いているか手計算で確認すること。
(vi) 行列の要素はdouble型にすること。
(vii) 行列の大きさを勝手に指定しないこと。つまり3x3の行列にしか対応できないメソッドというような特殊なメソッドにしないこと。
(viii) 何をしているのかわかるように、コメントを書くこと。
(ix) 「MethodSample12.java」のaddMatrixメソッドは課題要件を満たしていません。引数も戻り値も課題要件を満たしていない。
(x) (ii)と(iii)と(iv)では、まず行列Zを用意し、その行列Zに定数倍の行列や行列の和、積が代入されるようにしてください。
「多次元配列の受け渡し」の「MethodSample12.java」のaddMatrixメソッドは引数x,yの演算結果を引数zに代入していて、何もreturnしていませんが、元の配列の中身も期待通り変わります。
このような振る舞いが起こる理由は、配列が参照型の変数だから。テキストP195からP198を参照。
二つの行列の大きさによっては和や積が定義できないことがあるため、そのような場合に備えて例外処理を記述しておいた方が良いですが、この課題ではしなくても良いです。
例外処理をするのならばthrow new IllegalArgumentException("不正な引数による定義されない演算が実行されようとしました。");などとすると良いと思います。(テキストP430以降の「例外」を参照。)
問題8-9 (確認)
次のそれぞれ(1-1)から(1-7)に対する解答を、以下の(A)~(G)から選び答えなさい。解答には対応する英字だけで答えること。期末試験に向けての設問なので、問いと対応する答えの説明だけでなく、テキストをよく読み返しておくこと。
(1-1) javaでコメントを記述する方法を答えよ。
(1-2) リテラルとは何か。
(1-3) 1バイトは何ビットに相当するか。
(1-4) n++; と ++n; の動作の違いは何か。
(1-5) break文とcontinue文とは何か。
(1-6) 2進数「10101」をシフト演算子を用いて左に三つシフトしたときの値を2進数表記で答えよ。
//Sample8_9.java class Sample8_9{ public static void main(String[] args){ int a = 1; int b = 2; System.out.println(a/b); } }
(1-7) 上記のプログラムは実行すると0と表示されるが、小数点まで計算させて0.5と表示させるための方法を述べよ。
以下に、上の問題(1-1)~(1-7)の解答となる選択肢(A)~(G)を示す。上の問題にはそれぞれこの選択肢(A)~(G)で答えること。
(A) 整数同士の演算結果は整数となる。 整数同士の除算で小数を含む結果を得るためには、キャスト演算子を使って整数型からdouble型に型変換すればよい。 Javaで1÷2を0.5と表示させるためには、(double)a/bまたはa/(double)bまたは(double)a/(double)bなどとすればよい。
(B) 「10101」を左に三つシフトするので、「10101000」である。 三つ左にシフトするということは10進数で2の3乗倍するということ。 2進数「10101」は10進数で21である。21を8倍すると168。見方を変えると2進数「10101000」は10進数168に対応するということがわかる。 シフト演算子はint a = 21 << 3;のように使う。
(C) break文は、処理の流れを強制的に終了し、そのブロックから抜けるという処理のことである。for文やwhile文、switch文で使われる。 continue文は、繰り返し内の処理を飛ばし、ブロックの先頭位置に戻って次の処理を続ける、という文のことである。for文やwhile文で使われる。
(D) ++n;を前置インクリメント、n++;を後置インクリメントと言う。 変数に1を足すという目的だけならどちらも同じ動作をする。二つが異なるのは、代入するときである。 前置インクリメントは1を足してから値を代入し、後置インクリメントは代入してから1を足す。 変数から1を減らすときは--n;前置デクリメント、n--;後置デクリメントが使える。
(E) ビットとはコンピュータにとって最も基本となる単位のこと。「0 か 1 か」という情報ひとつが 1ビット(bit)にあたる。 それを 8桁にしたもの、8ビットで 1バイトという単位になる。つまり1バイトは8ビット。8ビットだと 0 から 255 まで表現できる。 00000000 が 0 で、11111111 が 255 にあたる。つまり 8ビットだと、256種類の情報を表現できる。256は2の8乗。 ドラクエなどのゲームでステータスの上限が255である理由もここにある。(厳密には1バイトを8ビット以外とするケースもあるのだがそれは無視して良い。)
(F) リテラルとは、一定の「値」をあらわすために用いられる、Javaの単語のようなものだと考えられる。 文字リテラルは1つの文字のこと。'A'のように、シングルクォーテーションでくくってコード中に記述する。 文字列リテラルは、複数の文字の並びのこと。"Hello"のようにダブルクォーテーションでくくってコード中に記述する。 数値リテラルは整数リテラルや浮動小数点数リテラルからなる。 シングルクォーテーションやダブルクォーテーションでくくらないで記述する。 整数リテラルで、8進数、16進数で数値を表記するときはそれぞれ、数値の先頭に0、数値の先頭に0xをつける。
(G) //を使うとその行の終わりまでJavaのコンパイラは無視して処理する。 /* コメント */を使うと間にはさまれたコメントをJavaのコンパイラは無視して処理する。 何をしているのかわかるように、コメントを書くように心がける。 しかしあまりに明らかなことや、無駄なことを書いて、プログラムを読みにくくしないようにすること。 たとえばa++;と書いてあればaに1を足すことは自明なのでわざわざaに1を足すとコメントに書かなくて良い。 書き方は自由で、どの程度コメントを書くかは人に依るが、プログラムの目的、メソッドの目的、特に説明が必要だと思われる注釈は最低限書くようにする。
問題8-10 (復習)
問題(2-1) 自分の学籍番号の下2桁をnとする。nを2進数で表したときに、3桁左にずらした結果を10進数で出力するプログラムを作りなさい。ただし次の(ⅰ)~(ⅲ)を3つとも必ず満たすこと。ソースコードと実行結果を提出せよ。
(ⅰ) 学籍番号を標準入力して結果を出力できるようにすること。
(例) キーボードから201020505を入力 (→ n=5 → 101 → 101000) → 40が出力される
ヒント:nの取り方
方法1 学籍番号を100で割って余りをnとする。
方法2 substringメソッドを使う。
str = 201020505; のとき、str.substring(7)=05;
str.substring( n )は文字列strの前からn+1番目以降の文字(部分文字列)を返します。
str.substring(str.length()-2)//文字列strの後ろ2文字分を切り出す
ヒント:2進数変換
方法1 String bn = Integer.toString( n, 2 ); //2進へ変換
方法2 String bn = Integer.toBinaryString( n ); //2進へ変換
(ⅱ) シフト演算子を用いること。(教科書lesson4)
(ⅲ) コメントを書くこと。プログラムの意図を知らない人でも即座に理解できるようなコメントをつけること。
実行結果例 学籍番号を入力して下さい => 201203505 n=5, 2進数= 101, nを3桁左の10進数 = 40です
問題(2-2)
実行はターミナルから行うようにして下さい。
課題5-8(1)のプログラムを以下の(ⅰ)~(ⅲ)のように書き換えなさい。ソースコードと実行結果(ターミナルから引数が分かるように貼りつけること)を提出せよ。
(i) 配列を定義して値を代入する書き方に変えなさい。
(ii) 最下段のクギの本数を表す変数をn とし、プログラム内に int n = Integer.parseInt(args[0]); の一文を用いなさい。
(iii) ボールの数を表す変数をk とし、プログラム内に int k = Integer.parseInt(args[1]); の一文を用いなさい。
(iv) 結果の表示には、for文を用いなさい。
以上の書き換えを正しく行い、javaコマンドラインからクギとボールの数を自由に設定できるようにしましょう。
最終的に以下のような出力結果が得られるようにしてください。
javac bin_simu.java java bin_simu 10 100000 |受け箱 | % ==================== 1 0.097 2 0.969 3 4.379 4 11.47 5 20.526 6 24.913 7 20.584 8 11.563 9 4.412 10 0.988 11 0.099
n と k を大きくして遊んでみましょう ^_^)b
ランダムウォークを無限回繰り返した場合に、点がある位置に存在する確率は正規分布で示される。(wikipedia 『ランダムウォーク』より)
↑を確認できると思います。
以下のベースプログラムを参考にして下さい。
//ベースとなるプログラム public class Assignment { public static void main(String[] args){ /* *必要な変数の宣言 */ int rCount = 0;//右に転がった回数 int n = Integer.parseInt(args[0]); // クギの本数 int k = Integer.parseInt(args[1]); // ボールの数/シミュレーション回数 // bin[i]は(i+1)番目のビンに入ったボールの数。ビンの数はn+1個。 int[] bin = new int[n+1]; Double lr; //右に転がる確率を格納 Double prob = 0.5; //閾値の設定 /* *シミュレーションの実施 * 外側のループ:(ボールの数) * ボールがスロットに入る * 内側のループ:5段の釘にぶつかって転がっていく様 * ボールがいずれかのビンに落ちる */ /* * Probability densityの計算 */ /* *結果の出力(for文を使う) */ } }問題(2-3)
y = sin x のグラフ、y = cos x のグラフ、y = sin x + cos x の三つのグラフをFrameを用いて描画しなさい。(ⅰ)~(ⅲ)に従うこと。ソースコードと作成したpngファイルを提出せよ。
(ⅰ) 三つのグラフは、x 軸 y軸を共有して、一つの図の中に重ねて描くこと。定義域は[0 ,2π]とする。
(ⅱ) グラフと共に氏名・学籍番号を描画すること。
(ⅲ) スクリーンショットを使ってpngファイルを作成すること。
以上。