情報処理 第11回講義資料
(補足)コマンド javac は java compiler 、コマンド java は java interpreter と呼ばれています。
画面上にメッセージを表示するだけの非常に簡単なプログラムを編集し、実行してみましょう。
- 以下のプログラムファイル Hello.java をダウンロードし、ホームディレクトリに移動するか、あるいは、テキストエディットを使って以下の内容をHello.javaというファイルに書き込みます。
- Hello.java を javac でコンパイルし ("javac Hello.java"とタイプします)、Hello.class を生成します。1.でダウンロードした場合には関係ありませんが、1で自分でファイルを作成した場合、ここでコンパイラ(javac)がエラーを報告したら、注意深くチェックして間違いの場所をなおします。この作業をデバッグ(debug)と呼びます。
- Hello.class を java で実行してみましょう ("java Hello" とタイプします)。
- メッセージの内容を変更してみましょう。
- javac とjava の使い方は、既に学習した man というコマンドで使い方を調べることができます。 (man javac, man java など)
// Hello.java というファイルには Hello というクラスを定義します。 public class Hello { public static void main(String argv[]) { System.out.println("Hello world!"); // Hello world! という文字列を表示します。 System.out.println("It's me!"); // It's me! という文字列を表示します。 return; // このプログラムを終わります // このプログラムを呼び出した場所に制御が戻ります。 } }
ここでは初歩的なJavaのプログラミングを学びます。Java言語の仕様はここではとてもカバーしきれないので以下のウェブサイトを参考にしてください。
- ハイパーワークブック26.1一歩一歩Java(推奨)
- Javaのオンライントレーニング(英語)
- jGuru: Language Essentials, Short Course Contents (英語)(推奨)
- JDK1.4.2 API仕様(英語)
- 一番おすすめのリンクは Google :)
- 基本的な事項
- 以下のプログラム(Test.java) をダウンロードしてコンパイルしてみましょう。基本的な約束事がいくつかあります。
- プログラムは命令(statement; ステートメント)の連続したものと考えることができます。記述された順番に(上から)命令を実行することになっていますが、中には順番が変わったり、繰り返しをするように指定することができます。
- 変数(variables;いろいろな値をとって変わる数)と演算子(operator; 演算方法を指定する記号)を使って計算を行うことができます。
- 変数は使用する前に、定義・宣言(declaration)をする必要があります。その際に、変数が、どのような 型(type;タイプ)なのかを宣言する必要があります。例えば、整数を取りうるもの(int) や実数を取りうるもの(double)などという指定ができます。
- 演算子は、加減乗除(+,-,*,/)に加えて数学ででてくる大抵の関数が使えます。例えば、%は除算の余りを表します。
- 青字部分はコメントです。実際にプログラムの中で"//"(ダブルスラッシュ)で始まる行や、"/*"と"*/"で囲まれた部分はコメントとなり、プログラムには影響を与えません。
- 基本的には、Test.java というファイルには一つのクラス class Test を定義します。クラスは、プログラムやデータをまとめた一つのまとまりの単位です。
// Test.java というファイルには Test というクラスを定義します。 // "//"という記号はコメント行の始まりを表します。 // それ以降の同じ行がコメントとなります。 /* このように"/*"と"*/"で囲まれた部分もコメントです。*/ public class Test // Test というクラスを定義します。 { public static void main (String argv[ ]) { // java Test とタイプしたときにここから処理が始まります。 int x, y=2; // xとy という整数型の変数を定義します。yは2が代入(初期化)されます。 // 命令の区切りは ";"(セミコロン)で表します。 double z=0.5; // zという実数型の変数を定義します。zは0.5で初期化されます。 x=2*(y+5)-4; // 一度定義された変数は数値を代入したり、参照されて計算に使うことができます。 y=x/2%3; // 変数は更に新しい値を代入することができます。このように各行は順番に実行・評価されていきます。 z=z+0.7; // 代入(=)の右辺にある変数は値を参照され、左辺の変数には計算の結果が代入されます。 // つまり、右辺のzは0.5という値が参照されて数値に置換され、左辺のzには1.2が代入されます。 x=(int)z; // 型の違う変数には型変換(キャスト)を行う必要があります。 // (int)は整数への(明示的な)キャストと呼ばれ、実数部分は切り捨てられます。 System.out.println("now x is " + x + ", y is " + y + " and z is " + z); // xとyとzを表示します。 } } }- 繰り返し (for)
- 繰り返しの命令を用いた例を見てみましょう。以下のファイルをダウンロードして、コンパイル、実行してみます。
public class Doubling // Doublingというクラスを定義します。 { public static void main(String argv[ ]) { int x=1, i; // xとiという整数型の変数を定義します。 // xは1で初期化(定義と同時に1が代入)されます。 for(i=0; i<=20; i=i+1) // iが0から始まり、i<=20という条件を満たす限り、 // 以下の{}で囲まれた部分を実行します。毎回の実行のあとにiには // 前の値に1を加えた値が代入されます。 { System.out.println(i + " : " + x); // iの値、" : "という文字列、xの値を連結して表示します。 //このように演算子は引数によって違う意味になることがあります。 x=x*2; // x に前の値を2倍した値が代入されます。 } } }- 条件判断 (if ... else)
- 繰り返しの命令を用いた例を見てみましょう。以下のファイルをダウンロードして、コンパイル、実行してみます。
public class Factors // Factorsというクラスを定義します { public static void main(String argv[ ]) { int x=2210; int i; for(i=2; i<=20; i=i+1) //以下のブロックを繰り返し実行します。 { if (x%i==0) //もしxがiで割り切れるなら以下を実行します。 { System.out.println("2210 is a multiple of" + i); } else //そうでない(xがiで割り切れない)なら以下を実行します。 { System.out.println("2210 is not a multiple of" + i); } } } } }- 条件判断付き繰返し (while)
- 条件判断付きの繰り返しの命令を用いた例を見てみましょう。以下のファイルをダウンロードして、コンパイル、実行してみます。
class TenMillion // TenMillionというクラスを定義します。 { public static void main(String argv[ ]) { int x=1, i=0; while(x < 10000000) //xが10,000,000以下の間、以下を実行します。 { i=i+1; x=x*2; } System.out.println(i + " times, result= " + x); } }
与えられた年月日 が何曜日にあたるかという曜日の計算方法の問題を考えましょう。実は、この問題に対しては以下に述べる「Zellerの公式」という、有名な曜日計算の公式があります。
変数year, month, dayを定義し、 year年month月day日の曜日を求めるとしましょう。(例えば、2005年月6月28日の場合、year=2005、month=6、day=28となります。)
ただし、1月と2月は、前の年の13月、14月として計算します。このときr = ( year + [ year/4 ] - [ year/100 ] + [ year/400 ] + [ (13month+8) / 5 ] + day ) % 7
が日曜日からの差分を表します。つまり、r=0が日曜日、r=1が月曜日、...、r=6が土曜日となります。
ただし、(1) x % y は、x を y で割った余りを表し、(2) [x] は、ガウスの記号で、xを超えない最大の整数を表します。
(Javaでは、2つの整数x, yで除算 x/yをすると商は自動的に[x/y](実数x/yを超えない最大の整数)となります。)
- さて、このZellerの公式を用いて、任意の year, month, day に対して曜日を表示するJavaのプログラムを作成してください。テンプレート(必要な部分を埋めて完成させる、不完全なプログラム)は以下からダウンロードできます。テンプレートに必要な部分を追加してください。
- Zeller.java (template)
- Zeller.java (answer)
class Zeller { public static void main(String argv[]) { // 任意の year, month, day に対し曜日を表示するJavaプログラム : : (この未完成部分を完成すること) } }- 出来上がったプログラムの出力とUNIXコマンドの"cal" の出力とを比較して、結果が正しいことを確認しましょう。
- 次に、このプログラムにUnixコマンドのように、パラメターを入力して、プログラムの動作を変更をする仕組みを追加してみましょう。以下のテンプレートに必要な部分を追加してみましょう。
- Zeller2.java (template)
- Zeller2.java (answer)
- X年(例えば、来年2006年)の「13日の金曜日」は1年の中で何回来るでしょうか?以下のテンプレートに必要な部分を追加しましょう。
- Zeller3.java (template)
- Zeller3.java (answer)
class NewZeller { public static void main(String argv[]) { // 2005年6月28日の曜日を表示する calc(2005,6,28); // 2005年6月29日の曜日を表示する calc(2005,6,29); } public static void calc(int year, int month, int day) { // 任意の year, month, day に対し曜日を表示するメソッド : } }
与えられた自然数n に対し、再帰的にメソッドを呼び出すことにより、n の階乗を計算するメソッドを書き、実際の動作を確かめましょう。HWBの再帰的メソッドの例を参考にしてください。以下のテンプレートをダウンロードし、ファイルを完成してください。
(ヒント: 漸化式を考えてみましょう。 nの階乗がAnであるような数列を考えると、漸化式はAn=n*An-1, (A1=1)となりますね。再帰的メソッドは、この漸化式をプログラムすることと考えれば理解しやすいかもしれません。)
- Factorial.java (template)
- Factorial.java (answer)
- Factorial2.java (answer2)
class Factorial { public static void main(String argv[]) { int i=5; int result=factorial(i); System.out.println(i+"!="+result); } public static int factorial(int k) { : } }
(注意)プログラムによっては、意図した動作をせずに、無限の繰り返し(無限ループ)の命令を実行してしまうことがあります。そのような場合には、control+cでプログラムの実行を強制中断することができます。
レポート課題3