61
Java プログラミング入門 福永 力 2003 4 月初版/04 4 月、05 6 月改訂 目次 1 最初の一歩 3 1.1 プログラムの作成 ....................................... 3 1.1.1 ソースファイルの作成 ................................ 3 1.1.2 プログラムのコンパイル、バイトコードの作成と実行 ............... 3 1.1.3 コメントを書く .................................... 4 1.1.4 課題 .......................................... 5 1.2 プログラミングを学ぶにあたって .............................. 5 1.3 HelloWorld プログラムの分析 ................................ 7 1.3.1 コメント ........................................ 7 1.3.2 クラスの定義 ..................................... 8 1.3.3 メソッド main の定義 ................................ 8 1.3.4 system クラスのメソッド読み出し .......................... 9 1.3.5 String[] args を使う .................................. 9 2 Java 言語の概要 11 2.1 変数と演算子 ......................................... 11 2.1.1 Java プログラムの基本要素 ............................. 11 2.1.2 変数と変数名 ..................................... 11 2.1.3 演算子 ......................................... 15 2.1.4 変数、演算子などのプログラム例題 ......................... 17 2.1.5 課題 .......................................... 19 2.2 式、文およびブロック .................................... 21 2.2.1 式(Expressions.................................. 21 2.2.2 文(Statements................................... 23 2.2.3 ブロック(Blocks................................. 24 2.2.4 課題 .......................................... 24 2.3 コントロール文 ........................................ 25 2.3.1 whiledo-while 文、不特定回数の繰り返し .................... 25 2.3.2 課題 .......................................... 26 2.3.3 for 文による繰り返し、特定回数の繰り返し .................... 27 2.3.4 課題 .......................................... 27 2.4 配列 .............................................. 28 2.4.1 課題 .......................................... 30 2.5 if 文による条件判断分岐 ................................... 31 2.5.1 課題 .......................................... 32 1

Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

Java プログラミング入門

福永 力

2003年 4月初版/04年 4月、05年 6月改訂

目 次1 最初の一歩 3

1.1 プログラムの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.1 ソースファイルの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.2 プログラムのコンパイル、バイトコードの作成と実行 . . . . . . . . . . . . . . . 31.1.3 コメントを書く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.1.4 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.2 プログラミングを学ぶにあたって . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.3 HelloWorldプログラムの分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.3.1 コメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.2 クラスの定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3.3 メソッドmainの定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.3.4 systemクラスのメソッド読み出し . . . . . . . . . . . . . . . . . . . . . . . . . . 91.3.5 String[] argsを使う . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2 Java言語の概要 11

2.1 変数と演算子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.1.1 Javaプログラムの基本要素 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.1.2 変数と変数名 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.1.3 演算子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.1.4 変数、演算子などのプログラム例題 . . . . . . . . . . . . . . . . . . . . . . . . . 172.1.5 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.2 式、文およびブロック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.2.1 式(Expressions) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.2.2 文(Statements) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2.3 ブロック(Blocks) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.2.4 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.3 コントロール文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.3.1 while、do-while文、不特定回数の繰り返し . . . . . . . . . . . . . . . . . . . . 252.3.2 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.3.3 for文による繰り返し、特定回数の繰り返し . . . . . . . . . . . . . . . . . . . . 272.3.4 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.4 配列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.4.1 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.5 if文による条件判断分岐 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.5.1 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

1

Page 2: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2.5.2 配列を使ったプログラミング課題 . . . . . . . . . . . . . . . . . . . . . . . . . . 322.6 参考Webページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3 数値計算と class Mathの利用 36

3.1 class Mathの変数、メソッド . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.2 Mathを使ったさまざまな例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.3 反復的に方程式 f(x) = 0の解を求める . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.3.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.3.2 二分法(はさみうち法) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.3.3 Newton-Raphson法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.4 数値積分とメソッドの自作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403.5 乱数発生とシミュレーション . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.5.1 ダイスゲーム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423.5.2 石ころなげゲーム:的に当たる数は? . . . . . . . . . . . . . . . . . . . . . . . . . 433.5.3 ゲームの理論:囚人のジレンマ . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

3.6 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4 アプレット(Applet)を使って図形を描く 46

4.1 画面構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.2 Class Graphicsを使った基本作図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.2.1 基本図形要素描出 appletプログラム例 . . . . . . . . . . . . . . . . . . . . . . . 464.2.2 DisplayShape.javaの分析 I Appletクラスの継承、Graphicsクラスの具体化 . . 494.2.3 DisplayShape.javaの分析 II Graphicsクラスの基本作画メソッド . . . . . . . . 504.2.4 色指定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514.2.5 文字列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524.2.6 Fontについて . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

4.3 参考Webページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544.4 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

2

Page 3: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

1 最初の一歩 

1.1 プログラムの作成  

1.1.1 ソースファイルの作成

これから Java言語を学び、Javaでプログラムを書き出していくのだが、そのためにはプログラム記述用のエディタを用意しなければならない。Linuxでは vi、emacs、あるいは redhat CDEにあるシステム固有のもの、Windowsではメモ帳、秀丸、TeraPadなどである。Wordを利用することも原理的に可能だがフォントを変えたり行端をそろえたりするわけでないのでシンプルなもので十分である。Linuxでは emacs、Windowsでは TeraPadというところか、標準的には。現在のOS(Operating Soft:Windowsとか Linuxという基本ソフト)のもとで、そのいずれかを起動。

エディターで以下の文章(短いながら javaプログラムです)を入力する。このオリジナルなファイルをソース(源、原始)ファイルという。

class HelloWorld {public static void main(String args[]) {

System.out.println("Hello, World!") ;}

}

プログラムを保存、ファイル名は HelloWorld.javaとする。いまのところ各行のもつ意味合いについてはおいておくことにする。  

1.1.2 プログラムのコンパイル、バイトコードの作成と実行

Windowsではコマンドプロンプト、Linuxでは端末ウィンドウを空けて以下のようなコマンドを打鍵する。

[prompt~ ]# javac HelloWorld.java[prompt~ ]# java HelloWorldHello、World![prompt~ ]#

気をつけるべきポイントは

• ファイル名の前半部(.javaより前)は一字一句大文字小文字も考慮してプログラムの先頭行 class

... の...と同じでなければならない。今の場合 HelloWorld。

• javac(翻訳指示)ではファイルのフルネームを入れる。

• java(実行指示)ではファイル名の前半部のみを指定。厳密にいうと実行すべきクラス名を指定する。しかし第 1項の制約により今のところファイル名前半部=(プログラム先頭で示したこのプログラムの)クラス名であるのでここではファイル名の前半部と考えておいて問題ない。

上記1行目(javac)で Javaの翻訳結果であるバイトコードを作成する。この javacはHelloWorld.javaを入力し、HelloWorld.classというファイルを出力する。この作業をコンパイル(compile)と呼んでいる。この中にバイトコードが含まれている。このバイトコードはコンピュータのOSによらない、独立したコードになっている。これは Java仮想マシーンの機械語で構成される。

3

Page 4: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

つまりこのHelloWorld.classがあれば、このファイルを Linuxにもっていって実行させてもWindowsで実行させても変わりなく同じ実行結果が得られる。再コンパイルさせる必要がない。そのかわり各OSはこのバイトコードを解釈して実行させる仮想マシーン(プログラムのこと)をもっていなければならない。このマシーンが搭載されていればOSの差異は意識せずプログラムを記述できる。この仮想マシーンを javaと呼ぶ(上記 2行目参照)。言い換えると javaというアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

バイトコードを解釈して今の自分の OS のもとでそのコードをあたかも自分の OSの独自のアプリケーションとして実行させることにある。

  

1.1.3 コメントを書く

上のプログラムは以下のように書いても実行においてなんら影響はない。/*......*/とか//をコメント(ライン)と呼ぶ。これはコンピュータのためというよりプログラムを書いた人、読む人の「覚え」である。

/*** The HelloWorld クラスは"Hello World!"という* メッセージを標準出力に表示します。

**/public class HelloWorld {

public static void main(String[] args) {// "Hello World!"と表示System.out.println("Hello World!");

}}

4

Page 5: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

1.1.4 課題

• Hello, 都立大学!とプリントさせるようにして、再度 javac、javaを行って実行させる。

• Hello, TMU!

I am Sen-ichi Hosiho, 0234567

のように 2行プリントさせるようにプログラムを改造。実行させよ。2行目の名前は各自の、数字は各自の学修番号とする。

• 上記の 2行のプリントを1つの System.out.printlnで行えるようにするにはどうしたらいいか考えよ、そして試してみよ。ヒント:改行、ベルをならす、タブストップなどのコントロールはエスケープシーケンスというエスケープ+制御文字の組み合わせの文字列で実行される。\(半角で¥あるいはバックスラッシュ)でエスケープを意味しその後にアルファベットか数字 1文字で制御を指定する。\nで改行を意味する。\7でベル(ビープ)、\tでタブストップなど。だから

System.out.println("ABC\nDE\F") ;

を実行させると出力は

ABCDEF

となる。

 

1.2 プログラミングを学ぶにあたってプログラムを通してなにができるかその基本を押さえておこう。その基本は 3点ありどんなプログラ

ムもつまるところこの 3点が複雑にからみあって成り立っているものであるということ。ここでは当面データ構造やプログラム書法については別のこととしておく。その 3点とは

1. プログラムは順序立てて上から下に実行される、

2. ある順序立てを繰り返す、繰り返し、 それと

3. ある順序立てをある条件では実行し、その条件が満たされなかったら実行しない、もしくはちがう順序立てを実行する条件分岐

である。まだやっとひとつのプログラムを作り上げたばかりであるが、それらについてごく簡単に見ていこう。細かい意味合いについては不問にしていく。まず以下の例である。エディターで作成したら GreetingSample.javaとして保存しよう。

class GreetingSample {public static void main(String args[]) {System.out.println("Good morning!") ;System.out.println("How are you?") ;System.out.println("Fine, thank you") ;System.out.println("Good bye!") ;

}}

5

Page 6: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

単純にプログラム頭部から 1行、1行実行がなされていく。次の例をみてみよう。繰り返しの例である。LoopSample.javaとして保存しよう。

class LoopSample {

public static void main(String args[]) {int loop, max=10 ;System.out.println("************") ;for(loop=0;loop<max;loop++) {System.out.println("* *") ;

}System.out.println("************") ;

}}

実行結果をみてみると以下のようになる。************* ** ** ** ** ** ** ** ** ** *************

このプログラムを実行してみると 10回{ System.out.println("* *") ;}という{....}の中の順序立て(この場合1命令のみ)を繰り返しているということが理解される。これが 2番目の繰り返しの実例である。そしてこのプログラムを改造して 3番目のポイントである条件分岐を概観しよう。以下のプログラム

は LoopIfSample.javaとする。class LoopIfSample {public static void main(String args[]) {int loop, max=12 ;for(loop=0;loop<max;loop++) {if(loop == 0) {System.out.println("************") ;

} else if (loop == (max-1)) {System.out.println("************") ;

} else {System.out.println("* *") ;

}}

}}

繰り返しを意味する for(....) {...}の{...}なかに if (...){...} else {...}という形の構造が表れているのに注意。これはもし()内が成り立つのであればすぐ直後の{...}内の順序立てを、そうでないなら(else)elseのあとの{...}の中の順序立てを行えという意味にとればよい。ほぼ英語の文意である。else ifはそうではないがもしととればよい。上の例では loopの値が 0のとき、あるいはmax-1(=11)のとき上蓋、下蓋を意味する************をそうでないなら側壁を意味する* *

を印字せよといっていることになる。ここまでで注意すべき点として

• 最初の行の出だしは常に classとなっている。そのあとに何かしらプログラムの名前を意味するようなものが出てきている。そしてそれはそのプログラムを保存する際のファイルネームの主幹をなす(あとは.javaで閉じる)。

6

Page 7: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

• 中括弧{と}がプログラムの構造を形作っている。常にかっこ開くとかっこ閉じる記号はバランスされていなければならない。プログラムの構造とはいまだ意味合いはわからないが逆に{...}をそう思ってしまえばよいようだ。

• 各行開始欄が微妙に行によって異なっている。しかしそれは先ほどみたプログラムの構造と関連している。

1.3 HelloWorldプログラムの分析前節で一般にプログラム言語でなにができるかを概観した。順序立てた実行、繰り返し、それと条件

判断と分岐であった。そして Javaで書かれた具体的なプログラムの例をいくつか見た。その内容、プログラムの計算概要は違うが、そのすべてに共通する構造があるのに気がついただろう

か。とくに最初の 2行はほとんど同じであるといってよい。1行目の classのあとの文字列が異なってはいるが。はじめのうちはこの 2行は Javaでプログラムを書く場合にはつねにこのように指定するものだ、と

決めてかかってもよい。しかしプログラムの分析を通してこれらについてここで少し基礎的な素養を学んでおこう。クラス、オブジェクト、具体化(インスタンシエーション)、変数、メソッドなど聞きなれぬことばが

でてくるが、言葉は覚えておいても関係や具体的な意味は漠然ととらえておいてよいだろう。前回のプログラムを 1行 1行振り返りながら javaの基本要素を概観しよう。ここで HelloWorld.java

を再掲しておこう。

/*** The HelloWorld クラスは"Hello World!"という* メッセージを標準出力に表示します。

**/class HelloWorld {public static void main(String[] args) {// "Hello World!"と表示

System.out.println("Hello World!");}

}

1.3.1 コメント/**

* The HelloWorldApp クラスは"Hello World!"という* メッセージを標準出力に表示します。

**/// "Hello World!"と表示

前節(1.1.3)でも記述したようにプログラムを読みやすくするために、コメントを多くプログラム内に埋め込もう。コメント=直接プログラムの演算結果には影響をあたえない。人間(プログラマーとプログラムを読む人の備忘録)

1. /* .... */で数行(1行以上)を指定。

2. //でそれ以降改行までをコメントとする。

  

7

Page 8: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

1.3.2 クラスの定義

public class HelloWorld{...}

クラスは java、C++のようなオブジェクト指向言語ではもっとも基本要素となる。クラスにそのクラスを運営するのに必要なデータ、さまざまな記述(関数)を定義する。記述(関数)をメソッド(Method)という。つまりクラスとはその中で使われる変数(後述)とそれを操作、加工するメソッドよりなる。つまり javaでは

class MyClass { ......}

というのがあると

MyClass {

}

の構造が含まれていることになる。classはキーワード。MyClassは任意の名前(変数名=固有名詞)で識別子と呼ばれる。識別子は javaの変数や定数、あるいはメソッドの名前のことである。識別子の名前付け規則というものがある。固有名を文字(アルファベット)ではじめ文字(アルファベット)、数字で構成される。アルファベットの大文字小文字は区別される。文字列の長さに制限はない。慣例としてクラス名は大文字で始め、変数、メソッド名は小文字で始める。途中単語の最初は大文字で他は小文字にする。なお javaの中で特別な言葉(複数)はキーワードとして利用が限定されている。これらを各種識別子として利用することはできない。いままでのHelloWorldには変数の定義はない(classの名前を除いて)。メソッドとしてmainが定義

されている。クラス定義が具体化(インスタンス)されたものをオブジェクトとよぶ。長く複雑な javaプログラムはその中に独自のクラスをいくつももち、また他の人々が書いたクラスも

数多く利用する。しかし当面はただひとつのクラスからなるプログラムを考察しよう。この場合このクラスは必ずmainメソッドを持たなければならない。  

1.3.3 メソッドmainの定義

public static void main(String[] args){...}

あるひとつの簡単な javaプログラムを作ったら実行はまずmainメソッドの先頭行から実行されていくことになる。

mainには 3個の修飾子(モディファイヤ)がある。それらは public static voidとなっている。当面この修飾子を無視して進めても(つまりこの3つは常にmainの前に決まってこの順序で並べるのだが)簡単に説明しておく。

1. publicをつけてこのクラスがどのオブジェクト(あるクラスが具体化される=インスタンス、あるいはオブジェクト化)からもわけ隔てなく呼び出せるようにする。 publicでないものは private。わけがあってそのメソッドを他のオブジェクトで利用されては困る場合 privateでメソッドを定義。

2. staticをつけてこのメソッドがクラスの普遍的な関数(メソッド)であることを指定。staticをつけないメソッドはクラスがインスタンス化されてオブジェクトとなるが、そのオブジェクトのみがそのメソッドを利用できる。クラスがインスタンス化されてオブジェクトになった場合、このstaticで定義された変数、メソッドはクラスからオブジェクトへそのままコピーされる。したがっていくつもクラスがインスタンス化されてもっすべてから共有されるもの(変数、メソッド)となる。

8

Page 9: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

3. voidをつけるとこのメソッド(関数)は戻り値がなにもないことになる。関数について以下の文章を参照。この関数(メソッド)に戻り値がない場合 voidとして明示しておく。

mainメソッドにはあらかじめ決められた引数がある。String[] argsである。これはあとで課題として実習しよう。

Javaでのメソッド(関数)の定義は基本的に以下のような形式になっている。

戻り値型指定 メソッド名(引数)

メソッドでなにか計算した結果を返えす場合、その結果を戻り値と呼ぶが、その型を指定する(型(type)とはあとで議論する)。引数とはメソッドに入力させる変数値である。アーギュメントとかパラメータとかいったりする。引数は複数あってかまわない。ちょうど数学の関数で

y = f(x1, x2, . . . , xn)

としたとき xiを関数fへの引数(パラメータ)とし、yを関数fの戻り値とみなすようなものである。  

1.3.4 systemクラスのメソッド読み出し

System.out.println("Hello World!");}

System.outでクラス Systemの変数を参照(System.out)することになり、それはもうひとつ他のクラス PrintStreamクラスを具体化したものを意味するようになる(ことになっている=決まり事)。printlnは PrintStreamのメソッドである。この場合 printlnは”で囲まれた文字列(リテラル)を標準出力装置に印字(タイプ)するということを行う。だから System.out.printlnはオブジェクト System.outのメソッド printlnを呼び出していることになる。  

1.3.5 String[] argsを使う

public static void main(String[] args) {...}

mainメソッドの引数 String[] argsを使うことを考えてみよう。javaのクラスを javaコマンドを用いて実行させるとき、パラメータを与えることができる。たとえばクラスの名前が以下のようにMessageOutだとすると、

MessageOut以下、スペースで区切られた各部分の文字列(全部で4部分)がargs[0]="Go", args[1]="Go",args[2]="Hanshin", args[3]="Tigers!" と argsという変数名のなかの第 0成分から第3成分までに格納されたことになる。以下のプログラムを作成し、実行させてみてその理解を深めてみよう。保存するプログラムの名前はMessageOut.java(大文字、小文字もこのとおり)とする。

/*** 課題:実行時に与えられた文字列(ストリング)の表示*/public class MessageOut {

public static void main(String[] args) {System.out.println("Hello TMU!");System.out.println("少しこった javaプログラム") ;System.out.println("今プログラム起動時に入力したメッセージは: ") ;System.out.println(args[0]) ;System.out.println(args[1]) ;System.out.println(args[2]) ;System.out.println(args[3]) ;}

}

9

Page 10: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

上記プログラムを以下のようなステップで実行する。

[prompt~]# javac MessageOut.java[prompt~]# java MessageOut Viva Our Hanshin Tigers!Hello TMU少しこった javaプログラム今プログラム起動時に入力したメッセージは:VivaOurHanshinTigers!

10

Page 11: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2 Java言語の概要 

2.1 変数と演算子  

2.1.1 Javaプログラムの基本要素

  この節で学ぶことはプログラムの基本要素である。この基本要素は多かれ少なかれどのプログラム言語でも共通に備えている。したがってなんらかのコンピュータ言語でプログラムを書こうとするならまずこの基本要素を押さえておかなければならない。以下の javaプログラムを BasicsDemo.javaとしよう。

class BasicsDemo {public static void main(String[] args) {

int sum = 0;for (int current = 1; current <= 10; current++) {

sum += current;}System.out.println("Sum = " + sum);

}}

簡単なプログラムだけど、非常に多くの概念をこの例は含んでいる。最初の2行はこれは Javaの特徴で、この部分は各種プログラミング言語によって書き方が異なる。一般的にヘッダー(頭部)と呼ばれている。さらにその他の基本要素はこのプログラム内にほぼ全部入っている。それらは

変数 データを一時的に保持するもの、名前(看板)と型(データタイプ)がある。

演算子 算術、論理演算、代入に必要な演算単位、つまり足すとか引く, かけるとかわるとか。

式、文、ブロック 演算子と変数の組み合わせで作る式、プログラムの基本単位、さらにそれを含む文、文のかたまり単位のブロック。

コントロール文 条件にしたがってプログラムの実行の流れを制御するための文、繰り返しや条件分岐。

2.1.2 変数と変数名

上記プログラム(BasicsDemo.java)では int sumと int currentという表記がある。これが変数宣言をしている。プログラム内で使う変数はすべて最初に型指定しなければならない。一般的には

type name

という形式をとる。typeは型と日本語で訳される。(基本データ)型には以下の表のKeywordのどれかを指定する。詳しくは

Java Tutorial HP

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html

11

Page 12: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

を参照のこと。

Keyword Description Size/Format

(integers) 整数byte Byte-length integer 8-bit長short Short integer 16-bit長int Integer 32-bit長 (一般的)long Long integer 64-bit長

(real numbers) 実数float Single-precision floating point 32-bit長 (IEEE 754)double Double-precision floating point 64-bit長 (IEEE 754)

(other types) その他char A single character 16-bit Unicode 文字boolean A boolean value (true or false) true or false

また以下の例のように int unInt = 4 などと書いて初期値を指定できる。以下は MaxVariablesDemo.java というプログラム。

class MaxVariablesDemo {public static void main(String args[]) {

// integers(整数)byte largestByte = Byte.MAX_VALUE;short largestShort = Short.MAX_VALUE;int largestInteger = Integer.MAX_VALUE;long largestLong = Long.MAX_VALUE;

// real numbers(実数)float largestFloat = Float.MAX_VALUE;double largestDouble = Double.MAX_VALUE;

// other primitive types(その他の基本型)char aChar = ’S’;boolean aBoolean = true;

// display them all(それらを全部示すと)System.out.println("The largest byte value is " + largestByte);System.out.println("The largest short value is " + largestShort);System.out.println("The largest integer value is " + largestInteger);System.out.println("The largest long value is " + largestLong);System.out.println("The largest float value is " + largestFloat);System.out.println("The largest double value is " + largestDouble);

if (Character.isUpperCase(aChar)) {System.out.println("The character " + aChar + " is upper case.");

} else {System.out.println("The character " + aChar + " is lower case.");

}System.out.println("The value of aBoolean is " + aBoolean);

}}

変数名には以下の原則がある。

1. 無制限長の文字列で最初の文字はアルファベット(途中空白を含むことはできない)、特殊文字として_と$。

• 許されるもの:ch_rad,GoodBye,theSister,onePoint,def$Int

12

Page 13: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

• だめなもの:2to10,key.Point,J-wave

• 同じようだが異なるものとして区別されるもの:I_am_Manと i_am_man

2. Keywordとして Javaが登録しているものは使えない。またこれ以外に true、false、nullもだめ。以下のものが使えない:

Keywords

abstract default if private throwboolean do implements protected throwsbreak double import public transientbyte else instanceof return trycase extends int short voidcatch final interface static volatilechar finally long super whiteclass float native switchconst for new synchronizedcontinue goto package this

3. Java プログラムの慣習で変数は最初の文字を小文字で、クラス名は大文字で命名する。もし変数名が2単語以上であれば2つめの単語からは最初の文字を大文字で、例:isVisible、myLove、anyCountDown。

4. 変数名はスコープ(Scope)内で有効である。

スコープとはその変数名の有効な領域をいう。スコープが違えば同じ名前で違う型、意味をもたせることができる。その場合、そのように再宣言しなければならない。変数のスコープはどこで変数が定義されているかによる。定義されるところによってメンバー変数、局所(Local)変数、メソッドパラメータなどと分類され

る。以下の図を参照。

基本データ型には次のように対応するラッパー(Wrapper)クラスがある。特定の基本データ型に対応するクラスの変数、メソッドを使ってそのデータ型の基本処理を行うことができる。

13

Page 14: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

型 ラッパークラスbool Booleanchar Characterbyte Byteshort Shortint Integerlong Longfloat Floatdouble Double

したがって上記プログラム中

int largestInteger = Integer.MAX_VALUE;

double largestDouble = Double.MAX_VALUE;

は Integer(Double)クラスの中に定義されているデータ MAX_VALUEの値を自分で定義した変数(型を指定して)に代入している。その型で一番大きい値を示している。

MaxVariableDemo.javaの実行例は以下のようである。この中で float、doubleなどの実数の最大値データ表示の末尾に E38とか E308となっているのは前半の小数点値× 1038あるいは× 10308を意味している。これを指数(Exponential)表示という。たとえば 1.284E2というのはつまり 128.4である。

The largest byte value is 127The largest short value is 32767The largest integer value is 2147483647The largest long value is 9223372036854775807The largest float value is 3.4028235E38The largest double value is 1.7976931348623157E308The character S is upper case.The value of aBoolean is true

以下は整数、実数それぞれを 2つ以上の精度のキーワードで宣言させちょっとした計算をさせるプログラムである。ファイルは variableDemo.java

class variableDemo {public static void main(String args[]) {

int index,base,two ;float x,y,z ;double xd,yd,zd ;

index=5 ;two = 2 ;base=index*two ; //* は乗算を意味するx=0.1f ;xd=0.1 ;y=x*base ; //整数と実数の乗算yd=xd*base ;

System.out.println("base is "+base) ;System.out.println("y is "+y) ;System.out.println("yd is "+yd) ;

x=1.0f ;xd=1.0 ;y=Short.MAX_VALUE ; // 16ビット整数の最大値を float実数に

14

Page 15: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

yd=Short.MAX_VALUE ; // 16ビット整数の最大値を double実数にz=x/y ; // /は除算を意味するzd=xd/yd ;

System.out.println("z is "+z) ;System.out.println("zd is "+zd) ;

}}

結果は以下のようである。

base is 10y is 1.0yd is 1.0z is 3.051851E-5zd is 3.051850947599719E-5

小数点の小数点以下の精度が floatと doubleで大きくことなることがわかる。  

2.1.3 演算子

演算子として以下のものがある。全部を覚える必要はまず今のところないが、知っている、知っていないで後々プログラミング技術で差がでてくる場合もある。

• 算術演算子

• 関係、条件演算子

• シフト、論理演算子

• 代入演算子

• その他

以下に詳しい。

Java Tutorial HP

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/opsummary.html

算術演算子算術(数値)計算でのみ有効

演算子 使い方 説明+ op1 + op2 op1と op2の和- op1 - op2 op1から op2を引く* op1 * op2 op1× op2/ op1 / op2 op1÷ op2% op1 % op2 op1を op2で割ったあまり(剰余)++ ++op opの値を利用する前に opの値を1増加++ op++ opの値を利用した後に opの値を1増加-- --op opの値を利用する前に opの値を1減少+ +op もし opが byte, short, or charなら、intとして扱う- -op op値を負にする

関係、条件演算子

15

Page 16: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2つの数(変数、定数)のさまざまな関係を計算する演算子(結果は真 (true)か偽 (false)のみ)演算子 使い方 真を返す場合

> op1 > op2 op1 は op2より大>= op1 >= op2 op1 は op2以上< op1 < op2 op1 は op2より小<= op1 <= op2 op1は op2以下== op1 == op2 op1 と op2 は等しい!= op1 != op2 op1 と op2 は等しくない&& op1 && op2 op1 と op2ともに true, op2を条件的に計算|| op1 || op2 op1 あるいは op2 は true, op2を条件的に計算! ! op opは false& op1 \& op2 op1 と op2 はともに真, つねに op1 と op2を計算| op1 | op2 op1と op2どちらかは真、つつねに op1 と op2を計算

^ op1 ^ op2もし op1 と op2 が異なるとき–つまりどちらかが真でどちらかがからなずそうでない場合

シフト、論理演算子演算子 使い方 説明>> op1 >> op2 op1のビットを op2個分右にシフト<< op1 << op2 op1のビットを op2個分左にシフト>>> op1 >>> op2 op1のビットを op2個分右にシフト (符号なし)& op1 & op2 ビットごとの and| op1 | op2 ビットごとの or^ op1 ^ op2 ビットごとの xor~ ~op2 ビットごとの complement

代入演算子基本は以下の形

op1 = op2 ;

これ以外に以下のショートカットがある。演算子 使い方 それはつまり+= op1 += op2 op1 = op1 + op2

-= op1 -= op2 op1 = op1 - op2

*= op1 *= op2 op1 = op1 * op2

/= op1 /= op2 op1 = op1 / op2

%= op1 %= op2 op1 = op1 % op2

&= op1 &= op2 op1 = op1 & op2

|= op1 |= op2 op1 = op1 | op2

^= op1 ^= op2 op1 = op1 ^ op2

<<= op1 <<= op2 op1 = op1 << op2

>>= op1 >>= op2 op1 = op1 >> op2

>>>= op1 >>>= op2 op1 = op1 >>> op2

他の演算子Javaはさらに以下の演算子を利用する。

16

Page 17: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

演算子 使い方 説明

?: op1 ? op2 : op3もし op1が trueなら op2を、そうでなければ op3を戻り値とする

[] type [] 長さ未定配列の宣言, 型を含む

[] type[ op1 ]長さ op1の配列を作る、new演算子とともに用いなければならない

[] op1[ op2 ]配列 op1の op2番目を利用、op2は 0から配列長-1までが範囲

. op1.op2 オブジェクト op1のメンバー op2を参照

() op1(params)パラメータ paramsを持ったmethod op1の宣言か読み出し

(type) (type) op1 キャスト (変換) op1 を typeに.

new new op1newオブジェクトか配列を作る. op1はコンストラクタか配列名

instanceof op1 instanceof op2 もし op1が op2のインスタンスであれば trueをもどす

2.1.4 変数、演算子などのプログラム例題

以下はまず 5個の値の平均値を計算してつぎにひとつデータを加えて 6個の平均値を計算するプログラムである(教育的見地からかかれたものでこんなプログラムを書いてはだめだけど)。

• 最初に 45、57、92、24、75の和をとりそれを平均値にするため個数(5)で割っている。ところが平均値の値がおかしい。293/5であるから 58.6が正しいのに 58.0となっている。これは整数と整数の割り算は自動的に整数の結果にまるめられてしまうからである。58となる。実数(float)の変数(average)に代入されて 58は 58.0となった。

• 正確な値を得ようとするなら実数/整数あるいは整数/実数の計算にさせてやらなければならない。プログラムでは整数→実数(この型変換をキャスティングというが)を (float)numberとして行っている。

• なお今まで出てきたかもしれないが、System.out.printlnの()に注目してほしい。文字列と変数(ここでは変数の型がでうであれ変数が直接カッコ内にある場合自動的に文字列に変換されるが)あるいは変数と文字列を+でつなげている。ストリング(String)型クラスでの演算子+は文字列と文字列の結合を意味している。いうまでもないがたとえば以下のプログラム断片

String abc,def,xyz ;abc="Pretty ";def="Boy" ;xyz=abc+def ;

では String型変数 xyzには”Pretty Boy”という値が含まれることになる。

• sum += 86という計算、number++という計算に注意。

class myAverage {public static void main(String args[]) {int number,sum ;float average;

// まず 5個の値の和number=5 ;sum=45+57+92+24+75 ;average=sum/number ;System.out.println("Number= "+number+" Sum = "+sum+" Average = "+ average );

17

Page 18: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

//// キャスティング

average=sum/(float)number ;System.out.println("Number= "+number+" Sum = "+sum+" Average = "+ average );

//// もう 1個データを増やして平均再計算

sum += 86 ;number++ ;average=sum/(float)number ;System.out.println("Number= "+number+" Sum = "+sum+" Average = "+ average );

}}

以下のプログラム例は都立大の学修番号から入学年度、学部、類、個人連番号を割り出そうとするものである。現在のところ

1. 上位 2桁で入学年度西暦の下 2桁を

2. 次の 1桁で学部・課程を(1から 5で 5学部,8で修士、9で博士、0はその他)

3. その次の桁は類・研究科。0~4あるいは 7が A類、5~6あるいは 8が B類

4. その次の 2桁は個人用の連番号で,

5. 最後の 1桁はチェックデジットで何の意味も持っていない番号である。計算方法はあるらしい。

この情報をもとにたとえば>> java myNumber 0456124

と入れるとその素性を明らかにしてくれるのが以下の myNumber.javaプログラムである。さまざまな演算が行われている。プログラムを追いながらそれら演算子の使い方を学んでほしい。

class myNumber {public static void main(String args[]) {int studentnumber,year, rui, gakubu, number ;char charrui ;

// 都立大学学修番号の分析(学部生のみ)

studentnumber = Integer.parseInt(args[0]) ;studentnumber = studentnumber/10 ;

year = studentnumber/10000 ;year += (year<10)? 2000:1900 ;

studentnumber = studentnumber % 10000 ;

gakubu=studentnumber/1000 ;

studentnumber=studentnumber%1000 ;rui = studentnumber/100 ;

charrui= ((rui<5)||rui==7)? ’A’:’B’ ;number = studentnumber%100 ;

System.out.print ("Entrance Year: "+year) ; //入学年度System.out.print (" Gakubu number: "+gakubu) ; //学部番号System.out.print (" "+charrui+"-Rui") ; //類System.out.println(" Number: "+number) ; //連番

}}

  

18

Page 19: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2.1.5 課題

1. OperatorTest.java

下のプログラムをまず読む。そして出力(プリント出力)がどうなるか予想してみよ。そして次にこのプログラムを実行させて答えを確認せよ。

public class OperatorTest {public static void main(String[] args) {int i=10 ;int n ;n = i++%5 ;System.out.println("n = " + n) ;n = i%5 ;System.out.println("n = " +n) ;n = ++i%5 ;System.out.println("n = " +n) ;

}}

2. BasicsDemo2.java

BasicsDemo.javaを改造して以下のように最後にもうひとつプリント文を入れて変数 currentの値を印字させたい。コンパイルエラーをなくすにはどうしたらいいだろうか。

class BasicsDemo2 {public static void main(String[] args) {int sum = 0;for (int current = 1; current <= 10; current++) {

sum += current;}System.out.println("Sum = " + sum);System.out.println("Current = " +current) ;

}}

3. SumInt1Limit.java

やはり BasicsDemo.javaを改造して Σni=1iの計算ができるようにせよ。nを実行時に入力できる

ように改造せよ。つまり

# java SumInt1Limit 1000

とすれば 1 + 2 + · · ·+ 1000までの和を計算するように。そのためにはデータを String[] argsで受け取る。入力データはひとつのみなので args[0]にデータが入力される。このままではしかし数字入力したといえどもただの文字並びでたとえば”1000”といれただけなのでこの文字列をプログラムのなかで整数字として認識させなければならない。それには以下の手法を使う。

int n = Integer.parseInt(args[0]) ;

ここでは基本データ型 intの wrapperクラス Integerのもつメソッド parseInt()を用いて文字列を整数に変換させている。

4. Sum2limits.java

前出の BasicsDemo.javaは 1+2+3+‥+10と計算している。任意の値をふたつ指定(start、last)し、その間の和を求めるように改造しなさい。整数 start、lastは java実行時に指定できるようにしなさい(つまり main(String[] args)に値をを引き出す。startは args[0]、lastは args[1]となる)。したがってこのプログラムを以下のように実行させると 11から 87までの和を計算することになる。

19

Page 20: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

# java Sum2limits 11 87

最後に結果をプリントしたあと、その結果が正しいかどうかを以下の式を計算させ、その答えsumkenをプリントさせることにより確認できるようにしなさい。

sumken = {last× (last + 1) - start× (start - 1)}/2

5. SecretCalc.java

以下のプログラム断片はどんな計算をしているか考えなさい。できたらその考えを裏付けるためにこの前後を整え正しい javaプログラムにさせて実行させなさい。

int answer = 1 ;int index = 1 ;for(int i=0;i<loop;i++) {

answer *= index++ ;}

なおこの前には loopに値を入力できるように

int loop = Integer.parseInt(args[0]) ;

をいれなさい。また後には answerをプリント出力できるようにしなさい。loopの値は 15以下に抑えてください。

6. ConeVolume.java

以下のプログラムは実行時クラス名(DiscArea)指定の後に円の半径(その単位は任意mmでもcmでもmでも Kmでもいい)を入力させその面積を計算するものである。

               public class DiscArea {public static void main(String[] args) {

double r = Double.parseDouble(args[0]) ;double s = Math.PI * r * r ;System.out.println("Disc area of radius "+ r +" = "+ s) ;

}}

これを参考に底面の円の半径(r)と高さ(h)を入力させ円錐の体積(v)を求めるプログラム ConeVolume.java を作りなさい。このプログラムの注意点を挙げておこう。

• java実行時に受け取ったデータは文字列(例えば 4.5678はただの文字の並びでありこの時点で実数 4.5678に結び付けられていない)である。

• これを Doubleクラスの parseDoubleメソッドが実数 4.5678と実数に変換している。

• Math.PIは π(円周率)である。

• この実行は例えば# java DiscArea 1.0とすると半径 1.0の円の面積を計算し標準出力にDisc area of radius 1.0 = 3.14159265358979

としてくれるものである。

• したがって 2つの変数 rと hをとり r=1、h=3の円錐の体積を計算するには例えば# java ConeVol 1 3とすればいいだろう。

20

Page 21: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

7. HourMinSec.java java実行時にパラメータひとつ入れる。例えば 10058。この入力された整数を秒数と考え何時間何分何秒であるか計算するプログラムをつくれ。なお args[0]文字列の整数変換は以下のようであるint s = Integer.parseInt(args[0]) ;

8. RenBunsu.java 最後に考え方はとてもむずかしいけれど、プログラムはとても簡単にできる問題。以下の無限正則連分数を計算するプログラムを作りなさい。繰り返し数 loopを始めに与えその繰り返し後のこの連分数の値をプリントする。プログラムの構造は課題 3と酷似している。answer

の計算式を考え付くことと answerは doubleにしなければならないことに注意。

1 +1

1 + 11+ 1

1+ 11+ 1

1+···

答えは以下のようになるはず。loop 式 answer値

1 1 + 11 2.0

2 1 + 11+ 1

11.5

3 1 + 11+ 1

1+ 11

1.6666....

4 1 + 11+ 1

1+ 11+ 1

1

1.6

 

2.2 式、文およびブロックプログラム中の単位としておおざっぱにいって式<<文<<ブロック

の関係がいえる。  

2.2.1 式(Expressions)

式とは単一の値を計算するたの変数、演算子、メソッド呼び出しを含めた系列(シリーズ)。前回変数、変数名の議論のときに掲げた MaxVariablesDemo.javaをもう一度以下に示そう。

class MaxVariablesDemo {public static void main(String args[]) {

// integersbyte largestByte = Byte.MAX_VALUE;short largestShort = Short.MAX_VALUE;int largestInteger = Integer.MAX_VALUE;long largestLong = Long.MAX_VALUE;

// real numbersfloat largestFloat = Float.MAX_VALUE;double largestDouble = Double.MAX_VALUE;

// other primitive typeschar aChar = ’S’;boolean aBoolean = true;

// display them allSystem.out.println("The largest byte value is " +largestByte);

21

Page 22: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

System.out.println("The largest short value is " + largestShort);System.out.println("The largest integer value is " + largestInteger);

  System.out.println("The largest long value is " + largestLong);

System.out.println("The largest float value is " + largestFloat);System.out.println("The largest double value is " + largestDouble);

if (Character.isUpperCase(aChar)) {System.out.println("The character " + aChar + " is upper case.");

} else {System.out.println("The character " + aChar + " is lower case.");

}System.out.println("The value of aBoolean is " + aBoolean);

}}

このプログラムにはまだ学習していないことが含まれている。それは

• if () {‥ } else {‥ }

if () {‥ } else {‥ }はコントロール文で項でくわしく取り扱うが、いわゆる条件判定のためのイフ文というもので()内の式が真であればすぐ次の {・・}で囲まれたブロックを、そうでなく偽であれば else後の {・・}ブロックを実行せよというもの。例えば char aChar=’S’;というところを char

aChar=’s’;としてみよ。upper caseとは大文字、lower caseとは小文字を意味する。このプログラムのなかで出てくる式について以下にまとめてみた。

aChar = ’S’ 文字型(char)変数に文字「S」を代入

"The largest byte value is " + largestByte "The largest byte value is "という文字列と整数型変数 largestByteの値の変換1) 文字列の結合

Character.isUpperCase(aChar); isUpperCaseというクラス Characterのメソッドを呼ぶ

Javaでは単純な 1項、2項演算式からその組み合わせの複合形までさまざまな式を組み立てることができる。しかしその場合式を構成している変数パートの各部分で型が一致していなければならない。つまり char型の変数と実数型の変数を組み合わせても意味がなく、エラーとなる。複合式を表現するとき、型のマッチング以外に式の評価優先順位を考慮しなければならない。たとえば今 x,y,zが同じ型であるとして

x*y*z

はどう書いても結果に影響はない(つまり x*z*y、x*(y*z)と表記しても)。しかし以下の式

x + y /100

は表記としてあいまいさが残る。Javaとしては厳密に優先順位が規定されているが、それがプログラムした人の考えと一致するとは考えられない。そこでプログラマーは自分のアイデアを厳密に反映させるために

(x+y)/100  

とか

x+(y/100)

1[注意]  文字列”1234”と計算結果の数字 1234 はコンピュータとしてはまったくべつの表現に属するもの。したがって計算結果をプリントさせるためにはその数字を「文字化」させなければならない。

22

Page 23: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

と表示させるべきである。演算子にはそれぞれ相対的な優先順位があり、それは今までの数学の常識にかなったものであるが、ものによっては注意を要するものもある。以下の表はもっとも優先度の高い演算子から降順に並べてある。かっこでくくる場合その中の式の評価の優先順位が上がるが Javaでは式に使われるかっこはすべて ()であり{[{()}]の区別は行わない。

名称 記述接尾演算子 [] . (params) expr++ expr--

単独演算子 ++expr --expr +expr -expr ~ !

creation あるいは cast new (type)expr

乗除 * / \%

加減 + -

シフト << >> >>>

関係 < > <= >= instanceof

等号 == !=

ビット毎 AND &

ビット毎排他的 OR ^

ビット毎 OR |

論理 AND &&

論理 OR ||

条件 ? :

代入 = += -= *= /= \%= &= ^= |= <<= >>= >>>=

  

2.2.2 文(Statements)

文は実行の最小単位となるものである。以下のような式が文となる。なお文はセミコロン;で終了。

• 代入式

• ++か–を使った式

• メソッド呼び出し

• オブジェクトのコンストラクター(クリエーション)式

それぞれの例として

aValue = 8933.234; //代入文aValue++;   //増加文System.out.println(aValue); //メソッド読み出しInteger integerObject = new Integer(4); //オブジェクト作成

さらにもう2つ。それは宣言文(declaration statement)で変数名を宣言するもの。たとえば

char aChar = ’s’ ;

(文字型変数 aCharを宣言し、その変数を初期化させsという文字を代入させる、とか

float aValue = 8933.234 ;

それともうひとつは次節に述べるコントロール文である。コントロール文は文の実行順序を制御する。今まで見たのは for文とか if文。  

23

Page 24: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2.2.3 ブロック(Blocks)

文をいくつかまとめたもので {文 1; 文 2; ‥ 文n }と中カッコでくくる。これは単文がおけるところならどこにでもおける。たとえば

int aModulo, aNumber, bNumber, workNumber ;‥‥if(aModulo != 0) {workNumber = aNumber ;aNumber = bNumber ;bNumber = workNumber ;

} else {System.out.println(".......") ;

}

では if文の条件があうときは3つの単体文を実行させたいので3文をカッコでくくりブロック化させている。それ以外では(else)単文であるがではさみブロック化させている。

int sum = 0;int sum2 = 0;for (int current = 1; current <= 10; current++) {

sum += current;sum2 += current*current ;

}

これは既出例の BasicsDemo.javaの一部を改変している。この例では繰り返し forのくりかえしがその後の{}全体に適用される。その結果このプログラムは Σ10

i=1iと Σ10i=1i

2をひとつの forループ後に計算させることができる。なおこの例でブロック化を忘れた場合

int sum = 0;int sum2 = 0;for (int current = 1; current <= 10; current++)

sum += current;sum2 += current*current ;

この直後に sum、sum2はどのような値を保持しているだろうか?  

2.2.4 課題

1. 初期に i=10として

i--%5 > 0

はどのような値になるだろうか。そして iの値は最終的にどうなるだろうか、確認するプログラムを以下の書き出しを参考に記述せよ。i=11ではどうか?ExpState.java

class ExpState {public static void main(String[] args) {int i = 10 ;

‥ ‥}

}

2. 2つの実数変数 xVaklueと yValueがある。プログラムの最初にxValue=12.345で、yValue=54.321であったとしよう。この値を入れ替えるプログラムを代入文を使って記述せよ。ExChange2.java

24

Page 25: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

class ExChange2 {

public static void main(String[] args) {

double xValue=12.345, yValue=54.321 ;

System.out.println("初期:xValue and yValue = " + xValue + "," + yValue) ;

‥ ‥ ‥System.out.println("最後:xValue and yValue = " + xValue + "," + yValue) ;

}

}

 

2.3 コントロール文コントロール文をふくまないプログラムを書くとコンピュータはプログラムの上から下に順番に文を

実行していくようになっている。しかしそのような単純な順序だての計算はまれでたいがいは条件によるプログラム部分の選択的実行や、ある部分の繰り返しが含まれるプログラムができあがる。このような実行順序を改変する文をコントロール文とよぶ。こまかくいうとコントロール文には4種類あるがここでは以下の3種類をみることにする。それで十分であろう。

文 Javaキーワード繰り返し while, do-while, for決定 if-else, switch-case分岐 break,continue,label:,return

  

2.3.1 while、do-while文、不特定回数の繰り返し

while文は以下の形をとる。

while(expression) {

statement(s) ;

}

expressionをまず計算、この expressionの型は booleanでなければならない。その値が真(true)であるかぎりその後の {‥ }を繰り返す。その計算過程でやがて expressionが真ではなくなり偽(false)になるであろう。そのときこの繰り返しはおわり {‥ }のあとに続く文が実行される。したがってwhile(true)などと書いてしまうとそれは無限ループを意味することになってしまいプログラムは永久に終わらなくなる。このような例の考えてみよう。データをいくつかとり統計処理をする。このときデータの個数はその

時々でちがう。ある場合は 100個のデータ、あるときは 23個とか。しかしその個数にかかわらずデータがこれ以上ないという時点で入力を終了しデータ解析(たとえば平均値をとる)を行いたい。より具体的にみるためあるクラスのテストの平均値の計算とする。この場合0点はいるがマイナスの

点をとる学生はいないとする。そこでデータ入力する際通常の成績入力が終わったとき、End-Of-Dataマークとして-1を入れるようにする。そうすると上のような統計処理プログラムは以下の構造となるだろう。以下の例は 3桁の整数すべての各桁の数の和をとるプログラムである。そのうちその和が 11になる

場合もとの3桁の数をプリントさせるプログラムである。WhileDemo.java

25

Page 26: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

class WhileDemo {public static void main(String[] args) {

int mil=1000 ;int ketasum = 0 ;int hundred,other,ten,one ;int index=100 ;while(index<mil) {

hundred = index/100 ;other = index%100 ;ten = other/10 ;one = other%10 ;ketasum = hundred+ten+one ;if(ketasum==11)

System.out.println("ketasum for "+index+" is 11") ;index++ ;

}}

}

do-while文は以下の一般形をとる。

do {

statement(s)

} while (expression) ;

この do-while文も不特定回数の繰り返しである。この繰り返しの継続条件はしかしループの最後におこなわれるため、最初に必ず1回 {‥ }は実行させられる。以下に例を示す。これは上記の例と変わらないが3桁の整数の各桁の和を求めその和の 25倍がもとの整数と等しいものがあるかどうかのサーチを行う。whileとの繰り返しの継続条件の計算位置がちがうので繰り返しの継続条件がすこしちがっていることに注意。DoWhileDemo.java

class DoWhileDemo {public static void main(String[] args) {int factor = 25;int mil = 1000 ;int ketasum = 0 ;int hundred,other,ten,one ;int index = 100 ;、do {hundred = index/100 ;other = index%100 ;ten = other/10 ;one = other%10 ;ketasum = hundred + ten + one ;if(ketasum*factor == index)System.out.println("Check Number: "+index) ;

index++ ;} while(index <= mil) ;

}}

2.3.2 課題

1. 3乗と2乗の差が 200より大きい最小の整数値を求めるプログラム。Int32200.java整数型変数 xの初期値を1から始めて x3 − x2 ≤ 200が成り立っている間は x の値を1つふやす。成り立たなくなった時点で上記の条件を満たす最小値に達したということでその値を印字させておわり。do-whileを使ってください。

26

Page 27: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2. 計算機 ε(イプシロン)(精度)を求める。CalcEpsilon.javaある実数 xは計算機では

x = a1/2 + a2/4 + a3/8 + a4/16 + .... + an/(2n)

と表される。a1から anは1か0である。nの値を知れば計算機の実数の精度がわかる。これを調べるプログラムを作ってみよう。それは

1 + 1/2, 1 + 1/4, 1 + 1/8, 1 + 1/16, ..........., 1 + 1/2n

と計算させて 1 + εを求める。いつか有限精度から 1 = 1 + εとなる。この時繰り返しをやめ、その一歩手前のεを求める。

  

2.3.3 for文による繰り返し、特定回数の繰り返し

コンパクトに規定回数の反復を行うのに非常に便利である。とくにベクトル型変数(配列)との組み合わせでおおきなプログラミングパワーを発揮する。for文は以下の形式である。

for(初期設定、終端条件、増加設定) {

文(複数)}

初期設定は繰り返しに先立ち一回初期化を行う、その設定をする。終端条件は繰り返しの終了の条件を各繰り返しの先頭で計算、その式が真であればループを継続、そうでなければループは終わる。増加設定は各ループの最後に実行される。これらの3つの設定は省略することも可能。for( ; ; )は無限ループを意味することになる。TempConv.java

public class TempConv {public static void main(String[] args) {int Low=-20, High=40 ;float Factor=1.8f, Bias=32.0f ;

// 温度単位 摂氏と華氏の変換表System.out.println("Temparature C to F Table") ;for (int degree = Low; degree < High; degree++) {System.out.print(degree+" C --- ") ;System.out.print((int)(Factor*degree+Bias)+ " F\t") ;if(degree%2 !=0 ) System.out.println() ;

}}

}

2.3.4 課題

1. 以下の図形の作図 DrawTriangle1.java

*******************************************************

27

Page 28: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2. 以下の図形の作図  DrawTriangle2.java

****************************************************************************************************

2.4 配列1つの変数名のもとで1つの値しか保持しない変数(スカラー)、以下の図でいうと iとか sum、と1

つの変数名で多数の値を保持できるもの、配列(Array)とがある。配列は多数の値の区別を番号(インデックス、0、1,2,3、‥)をもっておこなう。この番号を添字という。添字は 0以上で負の数は許されない。以下の図でいう vector[0]から vector[9]参照。配列のサイズは配列.lengthでプログラムで取得できる。

配列の定義、配列へのデータ入力

• 初期値をともなう配列の定義の仕方int varAar[]={0,1,2,4,8,16,32,64,128,256} ;

整数(4バイト)10個の領域を確保。

• 初期値をとらずに配列を定義  Idouble celsius[] = new double [36] ;

8バイト長の実数で 36個の領域を確保、newにより配列の各要素は zeroになる。

• 初期値をとらずに配列を定義  IIchar a[] ;

a = new char[20] ;

20バイトの領域確保。

• []の中に添字(index)をいれて、配列の添字番目の要素を操作できる。ここでは aの 3番目の要素に’c’を入れていたり、摂氏の温度データが入っている配列 24からから華氏へ温度の単位を変換し配列 Fahrenheitの 911番目に入力している。a[3]=’c’ ;

Fahrenheit[911]=Celsius[24]*1.8+32 ;

配列と for( ; ; ){....}を組み合わせてたくさんのデータの一括入力、一括処理が簡単にできる。以下の例は一括処理。

28

Page 29: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

public class ForDemo {public static void main(String[] args) {

int[] vector = { 32, 87, 3, 589, 12, 1076,2000, 8, 622, 127 };

int sum = 0 ;for (int i = 0; i < vector.length; i++) {

System.out.print(vector[i] + " ");sum += vector[i] ;

}System.out.println();System.out.println("Vector sum: "+ sum) ;

}}

public class ArrayDemo {public static void main(String[] args) {int lenData=50 ;long number[] = new long [lenData] ;long even[] = new long [lenData] ;long odd[] = new long [lenData] ;long fibonacci[] = new long [lenData] ;long irand[] = new long [lenData] ;double frand[] =new double [lenData] ;

for (int i = 0; i < lenData; i++) {number[i]= i ;even[i]=2*i ;odd[i]=2*i+1 ;fibonacci[i]=(i<2)? 1:fibonacci[i-2]+fibonacci[i-1] ;// [0,1)の一様乱数発生(詳しくは§4 class Math利用を参照)frand[i]=Math.random() ;long dum =(long)(frand[i]*(double)Long.MAX_VALUE) ;irand[i]=dum%100 ; //irandは [0,99]までの整数の一様乱数

}for(int i=0;i<lenData; i++) {System.out.print(number[i]+" ") ;System.out.print(even[i]+" ") ;System.out.print(odd[i]+" ") ;System.out.print(irand[i]+" ") ;System.out.print(fibonacci[i]+" ") ;System.out.print(frand[i]+" ") ;System.out.println() ;

}}

}

2次元配列上のプログラムは 2次元配列という行列形式の配列を使えばさらにデータ処理をコンパクト化できる。

public class Array2Demo {public static void main(String[] args) {int lenData=50 ;long overall[][] = new long [lenData][5] ;double frand[] =new double [lenData] ;

for (int i = 0; i < lenData; i++) {overall[i][0]= i ;overall[i][1]=2*i ;overall[i][2]=2*i+1 ;overall[i][3]=(i<2)? 1:overall[i-2][3]+overall[i-1][3] ;// [0,1)の一様乱数発生(詳しくは§4 class Math利用を参照)frand[i]=Math.random() ;long dum =(long)(frand[i]*(double)Long.MAX_VALUE) ;

29

Page 30: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

overall[i][4]=dum%100 ; //irandは [0,99]までの整数の一様乱数}for(int i=0;i<lenData; i++) {for(int j=0;j<5; j++)System.out.print(overall[i][j]+" ") ;

System.out.print(frand[i]+" ") ;System.out.println() ;

}}

}

2.4.1 課題

1. 前節例題を改変し平均値、標準偏差をもとめるプログラムを作成、データは32,73,25,57,34,90,68,83,45,76とする。

• 平均値はすべてのデータの和を個数で割った実数

• 標準偏差はすべてのデータの2乗の平均値と上で求めた平均値の2乗の差の平方根

2. 循環水送り問題  JunkanBaketsu.javaN人の人が両手にバケツを持ち、円周上に並んでいる。N人に対し以下の2つの繰り返しを行う。

(a) みんな右手のバケツに入っている水の半分を、左手のバケツに移す。

(b) 左手のバケツの水を全部、左隣の人の右手のバケツに加える。N番目の人の左バケツは 0番目人の右バケツに移す。

この 2回の繰り返しをステップと呼ぼう。最初に 0番目の人の右手のバケツに1リットルの水が入っていて、他のバケツは空だとする。ステップを繰り返し毎ステップごとの各自の右手(あるいは左手の)バケツの水量を表示するプログラムを作成する。このとき参加人数 Nとステップ繰り返し回数は最初に入力指定。考え方 i番目の人の右手のバケツの水量を right[i]、左手のを left[i]とする。先の水送り操作は

(a) left[i] = right[i]*0.5 ; right[i] = right[i]*0.5 (0<=i<n)

(b) right[i] = right[i]+left[i-1] (1<=i<n), right[0] = right[0]+left[n-1]

public class JunkanBaketsu {public static void main(String[] args) {

float right[] = new float[20] ;float left[] = new float[20] ;int i ;

// 初期設定 (nは人数、rは繰り返し総数)int n=10 ;int r=250 ;for(i=0;i<n;i++) {

right[i]= (float)0.0 ;left[i]= (float)0.0 ;

}right[0] = (float)1.0 ;System.out.println("Initial") ;for(i=0;i<n;i++) {

System.out.print(right[i]+" ") ;}System.out.println() ;

30

Page 31: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

//バケツリレーの開始for(int j=0;j<r;j++) {

// 繰り返し段階 I

// 繰り返し段階 II

System.out.println((j+1)+" times") ;for(i=0;i<n;i++) {

System.out.print(right[i]+" ") ;}System.out.println() ;

}}

}

3. 前節の例を見てみよう。その中に一様乱数 Math.random()を使って 0から 99までの整数の一様乱数の発生をさせる部分があった。この部分を抜き出す。そして乱数発生を 10000回繰り返す。配列 ranCount[i]をまずゼロにクリアさせ乱数発生で iがでたら(0 ≤ i ≤ 99)1カウントを増やす。最終的には ranCountには 0から 99までの乱数の出現回数がそれぞれ格納されている。それを順番に書き出しください。そしてその平均をとってください。100種類の整数の一様乱数発生を10000回行うので平均は 100近辺になるはず。できれば標準偏差をとり分布があまりあばれていないことを確認してください。

 

2.5 if文による条件判断分岐if文を用いて選択的にプログラムの一部を実行させたりとばしたりすることができる。たとえばプロ

グラムの実行過程で変数xの値をプリントさせたいがいつもそうではなくある変数の値が真であればプリントさせ、そうでなければスキップさせることができる。

boolean DEBUG = false ;

x = .. . . . . . . ;

if (DEBUG) {

System.out.println("DEBUG: x = " + x) ;

}

一般的には 以下のような単純型で書き表すことができる。

if (expression) {

statement(s)

}

ここで expressionの計算結果が真の時 {}内の statementsを実行させる、という意味をもたせる。ex-pressionの結果が偽であれば {}部はスキップされ、}の次に続く文が実行される。また expressionの結果が真であるときと偽であるときで異なる文のセットを実行させたいときは  

if(expression) {statement(s) //expressionが真の時

} else {  statement(s) //expressionが偽の時}

31

Page 32: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

もうひとつの形として場合場合が複雑になる場合

if(expression1) {statement(s) //expression1が真の時

else if (expression2) {statement(s) //expression1は偽だが,expression2は真の時

else if (expresison3) {statement(s) //expression1も expression2も偽だが expression3は真の時

else {

statements //expression1,expression2,expression3全部偽の時}

例題

public class SeisekiBunrui {public static void main(String[] args) {

int testscore = 76;char grade;

if (testscore >= 90) {grade = ’A’;

} else if (testscore >= 80) {grade = ’B’;

} else if (testscore >= 70) {grade = ’C’;

} else if (testscore >= 60) {grade = ’D’;

} else {grade = ’F’;

}System.out.println("Grade = " + grade);

}}

2.5.1 課題

1. ある鉄道運賃が(1)10Kmまでは一律 200円、(2)10~30Kmまでは 10Km越す分についてKmあたり 10円増し、(3)30Km以上では 30Kmを越す分についてさらにKmあたり 5円増しとなっている。目的駅までの距離 kから運賃を求めるプログラムを作る。FareCalc.java

2. 前節の例題は一人の成績について評価するものである。今 10人の受講生がいたとしてその成績が int[] testscore = {32,76,85,91,23,51,34,48,60,13}となっていた場合のこの10人の評価ができるように上の例題プログラムを改造する。for文を利用する。ClassSeiseki.java

  

2.5.2 配列を使ったプログラミング課題

1. Ripple.javaというプログラムを作る。まず以下のプログラムを読んでください。できれば実行してください。

public class Ripple {public static void main(String args[]) {

int ncell=75 ;int i,j,k,left,right ;

32

Page 33: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

int dcell[]=new int [ncell] ;int odcell[]=new int [ncell] ;for(i=0;i<ncell;i++) {

dcell[i]=0 ;odcell[i]=0 ;}

int ngeneration=ncell ;dcell[0]=1;dcell[1]=2 ;dcell[ncell-2]=2 ;dcell[ncell-1]=1 ;for (i=0;i<ncell;i++) {

if(dcell[i]==0) System.out.print(’ ’) ;if(dcell[i]==1) System.out.print(’#’) ;if(dcell[i]==2) System.out.print(’*’) ;

}System.out.println();for(i=0;i<ncell;i++) {

odcell[i]=dcell[i] ;}

}}

さてこのプログラムに続きを作ります。最後のの for文のあとに(つまり下から2行目と3行目の間に)以下のシナリオで示す通りのプログラムを付け加えてください。

(a) 以下のことを ngeneration-1回繰り返す

i. 以下のことを i=0から i<ncell繰り返すA. 1世代(generation)前の dcell[i]を参照する。その左の (i-1)の cell値(left)と右の(i+1)cell値 (right)を足す。もし i=0なら左の cell値は 0(left=0), 同じようにもし i=ncell-1であるなら右の cell値は 0(right=0)とする。

B. そのときの中央の(i)の cell値に応じて(それを pivotと呼ぼう)、以下のように次の世代の cell値(i)を決める。• pivot値が 0で、left+right値が 2以上なら、それは 2とする、そうでなければ

(left+right値が 2より小なら)0とする。• pivot値が 1ならどんな場合でも次世代 cell値は 0、• pivot値が 2で left値あるいは right値が 0である限り次世代 cell値は 1、そうでなければ(pivot値が 2であっても)次世代 cell値は 2

ii. 上の例のように cell値に応じて文字を出力(i=0,i<ncell)、行末に改行を挿入。iii. cell配列の世代交代をする。

(b) なにも後始末せずに終了。

2. 以下のような問題をプログラム化してください。voterRule.java

20人の投票者が独立に、両端の人の意見(0 or 1)を聞いて多数に従う。2人の意見が分かれているときには自分の意見は変えない。これを 5回繰り返す。ただし端は周期的とする。たとえば最初に

1 0 1 0 1 0 0 1 0 1 0 1 0 1 1 0 1 0 1 0

だとする。一回ごとのこれらの数値の変化を表示せよ。

3. やはりセルオートマトンの問題です。cellAM.java。 こんどは横一列の配列を以下のように定義します。

33

Page 34: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

int ncell=39 ;int []field = new int[ncell] ;int []nextfield = new int[ncell] ;

最初に fieldは field[19]=1以外全部 0とします。そして以下のようなルールに従って次の世代を考えます。i=0から ncell-1まで, field[i]はその 1世代前の field[i-1],[i],[i+1]の値で以下のようにさせます。

Index field[i-1] field[1] field[i+1] 次世代の field[i]のとるべき値7 1 1 1 16 1 1 0 05 1 0 1 14 1 0 0 13 0 1 1 02 0 1 0 01 0 0 1 10 0 0 0 0

つまり以下の図のように前世代の自分の値と両隣の値が次世代の自分の値になります。各欄は 0か1しかとれないので上の8つの組み合わせが考えられます。

そしてあるパターンの 0,1の組み合わせで次に 1か 0になるかは表の右端に与えられています。これを 20世代繰り返すと以下のような図になります。出力 1は「1」、0は「.」で表示させています。なお各世代 i=0から i=ncell-1まで field[i]の値を変えていくのですが i=0で次世代を考えるときは i=38,i=0と i=1の組み合わせ,i=ncell-1のときは i=ncell-2,i=ncell-1それと i=0として考えます。

...................1...................

..................1.1..................

.................1.1.1.................

................1.1.1.1................

...............1.1.1.1.1...............

..............1.1.1.1.1.1..............

.............1.1.1.1.1.1.1.............

............1.1.1.1.1.1.1.1............

...........1.1.1.1.1.1.1.1.1...........

..........1.1.1.1.1.1.1.1.1.1..........

.........1.1.1.1.1.1.1.1.1.1.1.........

........1.1.1.1.1.1.1.1.1.1.1.1........

.......1.1.1.1.1.1.1.1.1.1.1.1.1.......

......1.1.1.1.1.1.1.1.1.1.1.1.1.1......

.....1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.....

....1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1....

...1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1...

..1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1..

.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.

34

Page 35: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

また上の表で index=2のときの次世代 field[i]を1とさせるだけで以下のように図は変化します。

...................1...................

..................111..................

.................1.1.1.................

................1111111................

...............1.11111.1...............

..............111.111.111..............

.............1.1.1.1.1.1.1.............

............111111111111111............

...........1.1111111111111.1...........

..........111.11111111111.111..........

.........1.1.1.111111111.1.1.1.........

........1111111.1111111.1111111........

.......1.11111.1.11111.1.11111.1.......

......111.111.111.111.111.111.111......

.....1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.....

....1111111111111111111111111111111....

...1.11111111111111111111111111111.1...

..111.111111111111111111111111111.111..

.1.1.1.1111111111111111111111111.1.1.1.1111111.11111111111111111111111.1111111111111.1.111111111111111111111.1.111111

これらを出力するプログラム cellAM.javaを作ってください。出力はどちらかひとつでかまいません。しかし 1ヶ所かえるだけで両方ちゃんと出力できるか確認してください。ややっこしいのは 3個の fieldの値を比べるところです。以下のようにしてみたらどうでしょうか。

int i1=i-1 ;int i2=i+1 ;if(i1<0) i1+= ncell ;if(i2>38) i2 -= ncell ;index=0 ;if(field[i1]==0) {if(field[i]==0) {

if(field[i2]==0) index=0 ; //0,0,0else index=1 ; //0,0,1

} else {if(field[i2]==0) index=2 ; //0,1,0else index=3 ; //0,1,1

}} else {if(field[i]==0) {if(field[i2]==0) index=4 ; //1,0,0else index =5 ; //1,0,1

} else {if(field[i2]==0) index=6 ; //1,1,0else index=7 ; //1,1,1

}}

2.6 参考Webページ今まであまり省みなかったがそれでもいくつかの基本算術関数(sin , cos , log ,

√)などが定義されているクラスがある。どのような関数が定義されているか、あるいはそれらの Javaプログラムからの利用の仕方についてはhttp://java.sun.com/products/jdk/1.2/docs/api/java/lang/Math.html(英文)を参照してほしい。

35

Page 36: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

3 数値計算と class Mathの利用3.1 class Mathの変数、メソッド  class Mathは Java Development Kit (JDK)が提供する共用 classで数学的定数を class変数とし

て、数学関数を classメソッドとして用意している。class Mathは public class Mathとして定義されている。class定義の前に publicをつけているの

で、classをインスタンス化(classを他の classが利用するとき具体的な変数として名前付けすること)なしにこの classの中で定義されている変数、メソッドを利用できる。以下にこの classで定義されている定数、メソッドをまとめた。なおこの class(public class)の変数、メソッドを利用するときはMath.という接頭辞を必ずつける。実数で戻り値があるメソッドはすべて型が doubleであることに注意。

定数 型 記述E double 自然対数の底 e

PI double 円周率 π

戻り値型メソッド名 double float int long 記述abs(double) ○ 絶対値abs(float) ○ ○ ○ 絶対値abs(int) ○ ○ 絶対値abs(long) ○ 絶対値acos(double) ○ arc cosasin(double) ○ arc sinatan(double) ○ arc tanatan2(double,double) ○ (x,y)→ (r,φ)のφceil(double) ○ 小数点値切り下げ(doubleで戻す)cos(double) ○ cosexp(double) ○ 指数関数 expfloor(double) ○ 小数点値切り上げ(doubleで戻す)log(double) ○ 自然対数max(double,double) ○ 2つの数値の最大値max(float,float) ○ 2つの数値の最大値max(int,int) ○ 2つの数値の最大値max(long,long) ○ 2つの数値の最大値min(double,double) ○ 2つの数値の最小値min(float,float) ○ 2つの数値の最小値min(int,int) ○ 2つの数値の最小値min(long,long) ○ 2つの数値の最小値pow(double,double) ○ pow(a,b)=ab

random() ○ 0.0から 1.0までの一様乱数値rint(double) ○ 引数の四捨五入値round(double) ○ 引数の四捨五入値round(float) ○ 引数の四捨五入値sin(double) ○ sinsqrt(double) ○ 平方根tan(double) ○ tan

36

Page 37: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

3.2 Mathを使ったさまざまな例

3.3 反復的に方程式 f(x) = 0の解を求める3.3.1 はじめに

まず表題の議論に入る前に計算精度について確認しておこう。以前の課題の計算機精度εについてでも考察したが実数には有限の精度がある。これは実数型 doubleと floatで違う。たとえば 1/10を 10回、1/100を 100回、1/1000を 1000回足すという計算を 1/1000000000まで繰り返そう。すべてにわたって当然結果は1になるべきだが。以下にそのプログラムと計算結果を示す。ここで class Mathの powというメソッドが利用されていることに注意。

class powerSum {public static void main(String args[]) {float fsum,fx ;double dsum,dx ;int i,k,n ;for(k=1;k<9;k++) {n=(int)Math.pow(10.0,(double)k) ;fx=1.0f/n ;fsum=0.0f ;dx=1.0/n ;dsum=0.0 ;for(i=0;i<n;i++) {fsum += fx ;dsum += dx ;

}System.out.println(n+" "+fsum+" "+dsum) ;

}}

}

この結果は以下のようになる。10 1.0000001 0.9999999999999999100 0.99999934 1.00000000000000071000 0.9999907 1.000000000000000710000 1.0000535 0.9999999999999062100000 1.0009902 0.99999999999808381000000 1.0090389 1.00000000000791810000000 1.0647675 0.99999999975017100000000 0.25 1.0000000022898672

float型で計算するとすでに n=1000あたりでも答えの精度の有効数字がずれてきてしまう。double型では 1000000000でもそれなりの計算結果を保持している。このことに注意してほしい。しかし実数計算の精度を 64ビットにすれば精度は満足できるかもしれないがプログラムの容量は大きくなるし、実行速度も遅くなる。あまり精度を気にしない実数計算(たとえばグラフィックスでの座標計算など)でむやみやたらと doubleで計算させても意味はあまりなくなる。またその他の要因で数値計算の精度が悪くなる場合もあるので注意しよう。それらは課題で考えていこう。

3.3.2 二分法(はさみうち法)

いわゆる科学技術計算ではきれいに f(x) = 0となる xが求められるような関数の解を求めるのではなく数値的にでしかxを求めることができない場合が多い。その場合なんらかの方法で反復を繰り返して求める数値を精度的に満足のいく範囲でもとめることになる。いくつか方法が考案されているがここでは二分法というのを見てみよう。以下の図に示すように関数 f(x)が aと bの間で 1回だけ符号をかえることがわかっているとする。そのような a,bを初期値として話をすすめる。この場合以下の反復により f(x) = 0の解を求めることができる。

37

Page 38: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

初期値 a(f(a)<0)および b(f(b)>0)を与える、求める解の精度 dを与える、|a-b|>dの間、以下{}内を繰り返す{   x=a+b/2

y=f(x)

もし y>0 ならば b=xとする   そうではなく y<0ならば a=xとする }

xが求める解であるとしてその値をプリント

これに基づいて f(x) = x2 − r = 0をとなる xを求めてみよう。以下のプログラムである。とうぜん解は

√(r)である。ここで実数 rとして適当な正の実数値を入れてみるのだが以下のことを考慮して

1/4 < r ≤ 1 の範囲のみを考えてみる。それは適当な整数mを用いて rを

r = 4m · r′ (1/4 ≤ r′ ≤ 1)

と表すことができるからで√

r = 2m√

r′

となるのでコンピュータを使って平方根計算をするには 1/4 < a ≤ 1の範囲のみ実数計算させあとは整数計算を優先させるほうが速いからだ。ここでは r = 1/4としてみよう。結果はもちろん 0.5である。rの範囲を限定させれば初期値範囲も a=0,b=1と固定できる。なお以下のプログラムでは中間結果をみたくて余計なプリント文を入れている。

class binSolve {public static void main(String args[]) {double a,b,x,y,d,r ;int index=0 ;

a=0.0 ;b=1.0 ;d=1.0e-7 ;x=1.0 ;r=0.25000000004 ;

while(Math.abs(a-b)>d) {x=(a+b)*0.5 ;y=x*x-2.0 ;if(y>0) b=x ;else a=x ;System.out.println("index = "+index+" x= "+x) ;index++ ;

}

38

Page 39: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

System.out.println("Final answer= "+x+" after "+index+" repeats") ;}

}

結果は以下のようであった。a=0,b=1なので今の場合偶然第1回目の繰り返しでいきなり正解に達しているが a,bの差が大きく whileループの条件は満たされるのでさらに繰り返しは続いていく。

index = 0 x= 0.5index = 1 x= 0.75index = 2 x= 0.625index = 3 x= 0.5625index = 4 x= 0.53125index = 5 x= 0.515625index = 6 x= 0.5078125index = 7 x= 0.50390625index = 8 x= 0.501953125index = 9 x= 0.5009765625index = 10 x= 0.50048828125index = 11 x= 0.500244140625index = 12 x= 0.5001220703125index = 13 x= 0.50006103515625index = 14 x= 0.500030517578125index = 15 x= 0.5000152587890625index = 16 x= 0.5000076293945312index = 17 x= 0.5000038146972656index = 18 x= 0.5000019073486328index = 19 x= 0.5000009536743164index = 20 x= 0.5000004768371582index = 21 x= 0.5000002384185791index = 22 x= 0.5000001192092896index = 23 x= 0.5000000596046448Final answer= 0.5000000596046448 after 24 repeat

3.3.3 Newton-Raphson法

関数の曲線が以下の図のように解付近で単調になっているなら関数の勾配(導関数)を使うことにより効率的に解を見出すことができる。

精度dを与えておく。初期値 x(n=0)も与えておく。|x(n + 1) − x(n)|/x(n + 1) > dの間、以下の{}の計算を繰り返す。{

1. 現在点 (x(n), f(x(n))における関数の接線の傾き f ′(x(n))を計算

39

Page 40: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

2. y − f(x(n)) = f ′(x(n))(x − x(n)) が x軸と交わる点を計算、次の点すなわち x(n + 1)とし、これを計算。

x(n + 1) = x(n) − [f(x(n))/f ′(x(n))]

}

精度が満たされ反復繰り返しを終えたら x(n + 1)を解としてプリント。以下にプログラムを示す。収束の様子を調べたかったのでここでも while ループのなかにプリントを入れてみた。平方根をとるべき数を実行時に入力させたかったので doubleの wrapperクラス Doubleの ValueOfメソッドを利用した。そのため変数 rrを Doubleクラスとしてインスタンス化した。classDoubleの rrの値を double型に変換させなければならずやむなく doubleValueという class Doubleのメソッドを利用した。前回初期値として2つの値 a、bを必要とした。今回は初期値は xの出発点である。固定して x=1にする。

class newtonSolve {public static void main(String args[]) {double d,xold,xnew,r ;

int index=0 ;Double rr ;rr=Double.valueOf(args[0]) ;d=1.0e-7 ;xold = 2.0 ;xnew = 1.0 ;r=rr.doubleValue() ;while(Math.abs(xnew-xold)/xnew > d) {xold = xnew ;xnew = (xold+r/xold)/2.0 ;index++ ;System.out.println("index= "+index+" xnew="+xnew) ;

}System.out.println("Final x = "+xnew+" after "+index+" repeats") ;

}}

結果は以下のようである。xold=2.0を最初に入れているがこれはまったく任意の値でいいが、以下に続く whileループの条件を満たすようにする。収束状況は前回の二分法に比べて格段とよくなっている(なぜだろうか?)。

index= 1 xnew=0.6250000002index= 2 xnew=0.512500000356index= 3 xnew=0.5001524394232112index= 4 xnew=0.5000000236305733index= 5 xnew=0.5000000004000005Final x = 0.5000000004000005 after 5 repeat

3.4 数値積分とメソッドの自作いまは定積分を完全に数式の変形により(求められる場合は)求めてしまうアプリケーションプログ

ラムもあるが、やはり素早くどのような関数でも普遍的にその定積分が求められる数値積分は大変便利である。定積分は結局面積の計算ということなので2次元の関数 y=f(x)と積分の上限、下限と y=0で囲まれ

る図形を効率的に面積を求められやすい長方形や台形に近似させるということが出発点になる。以下に定積分数値計算を

A =∫ 1

0

41 + x2

dx = π

40

Page 41: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

を元に考えてみよう。以下の図は xが 0から1までの上記の関数の振る舞いである。0 ≤ x ≤ 1を均等区間割しその区間内

の関数の面積を左は四角形で、右は台形で近似したものである。いうまでもなく関数の性質によるだろうがなめらかな関数は区間の幅をうまく取れば台形近似で定積分を精度良く求められるだろうことがわかる。

以下のプログラムは台形近似計算プログラムである。このなかに今まで慣れ親しんできたmain メソッド以外に

static double func(double x) {...}

static double intrap(double a, double b, long ndivide) {...}

というのがある。これは自分でこのクラスにメソッドを加えたものである。最初の funcは戻り値が doubleであり、引数

として()内で doubleの値をとっている。y = f(x)に対応している。戻り値は return(y)で指定される。さらに staticという修飾語もあるがとりあえず今必要のない概念なので忘れておく。statuc main

から呼び出される場合この staticという修飾語を必要とする。今はだから必ずつけておく。つづいて intrapというメソッドは3個の入力引数を必要としている。doube変数で aと b、long変数

で ndivideである。これは funcの [a, b]の定積分値を計算するものである。ndivideは [a, b]の区分けの数である。メソッドは通常計算を引数の値を変えて何回も計算したいとき、あるいはなにか普遍的な計算機能と

して独立にさせておきたいときに使う。このプログラムは数値計算にともなう誤差をはっきり強調させるためすべて 32bitの実数計算(float)

でおこなった。

class trapezoidInt {static float func(float x) {float y ;y=4.0f/(1.0f+x*x) ;return(y) ;

}

static float intrap(float a, float b, long ndivide) {float h, area ;

area = 0.0f ;h=(b-a)/ndivide ;for(int i=0;i<ndivide-1;i++) {float left=a+i*h ;float right=left+h ;area += (func(left)+func(right))*0.5 ;

41

Page 42: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

}area *= h ;return(area) ;

}

public static void main(String args[]) {long N ;

for(int k=3;k<21;k++) {N=Math.round(Math.pow(2.0f,(float)k)) ;float area = intrap(0.0f,1.0f,N) ;System.out.println("N = "+N+" Area = "+area+" "+area/Math.PI) ;

}}

}

結果は以下のようになる。これでは区間を細分化させれば π値に近づいていくが、さらに細分化させすぎるとかえって数値計算にともなう誤差が積まれていきかえって精度が落ちていくことがわかる。

N = 8 Area = 2.8723955 0.9143118895951402N = 16 Area = 3.0119133 0.9587217795785631N = 32 Area = 3.0779376 0.9797379680907292N = 64 Area = 3.1100562 0.9899616229133766N = 128 Area = 3.1258965 0.9950037444496709N = 256 Area = 3.1337624 0.9975075400174159N = 512 Area = 3.1376815 0.9987550361238234N = 1024 Area = 3.1396375 0.9993776458121655N = 2048 Area = 3.1406147 0.9996887229833642N = 4096 Area = 3.1411057 0.999844982533376N = 8192 Area = 3.1413474 0.9999219359980247N = 16384 Area = 3.1414688 0.9999605645123306N = 32768 Area = 3.14153 0.9999800684969606N = 65536 Area = 3.1415596 0.999989478979817N = 131072 Area = 3.1415389 0.9999828764636194N = 262144 Area = 3.1415486 0.9999859879942413N = 524288 Area = 3.1412358 0.9998864190143406N = 1048576 Area = 3.140424 0.9996280101907419

3.5 乱数発生とシミュレーションさていままで多少硬い話が続いたのでちょっと直感的な話題を考えてみよう。それは乱数(random

number)を使ったものである。この乱数の用途は多岐にわたるがよく使われる代表は確率過程のシミュレーションである。たとえばギャンブルは 0か 1、あるいは 1から 6までの数字を使うダイス、さらに多くの数字を使うルーレットなどで一般的には出た所勝負である。確率過程である。このシミュレーションに乱数が使われるのはくどく説明するまでもないだろう。

3.5.1 ダイスゲーム

次のプログラムをみてもらおう。class Mathの random()というメソッドを使って整数の 0から最大整数まで出現する整数乱数を完成させそれを 6で割ってあまりをとっている。6である整数を割れば剰余は 0から 5のまでの 6通りとなりその数に 1を足してダイスシミュレータが完成される。つづいてmainメソッドでは Ntotalのダイスをふらせ出た目のカウントを行っている。安全のため最

初の 20回は出た目も横 1列に書きださせている。プログラムを以下に示す。

class diceOne {

static int dice() {int irand = (int)(Math.random()*(double)Integer.MAX_VALUE) ;return(irand%6+1) ;

}

42

Page 43: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

public static void main(String args[]) {int Ntotal=3600 ;int value[] = {0,0,0,0,0,0} ;

for(int i=0;i<Ntotal;i++) {if(i<20)System.out.print(dice()+" ") ;

for(int j=1;j<7;j++)if(dice()==j) value[j-1]++ ;

}System.out.println() ;for(int j=0;j<6;j++) {int jj=j+1 ;System.out.println("Dice(" +jj+"): "+value[j]+"/"+Ntotal) ;

}}

}

この結果(の 1例)は以下のようである。この乱数を用いた計算は毎回毎回このようになるとは限らない。大体統計的変動内において数は一致するが正確には一致しない。それは乱数が毎回毎回Math.random()関数を呼ぶたびに違う値を指し示すからだ。計算機上では乱数は擬似乱数と呼ばれ厳密にランダムな数ではなくある数列に基づいて生成される。ということはもしいつもいつも初期値が同じであれば毎回同じ乱数数列が生成されるはずである。この class Mathの random()はその悪弊を廃し、初期値を適当な数(今の時刻の分秒の整数値とか)に設定させて見かけ上は常にでたらめな数が出るように工夫されている。

5 4 5 4 3 2 1 5 5 6 2 2 5 2 3 3 1 5 3 1Dice(1): 607/3600Dice(2): 581/3600Dice(3): 572/3600Dice(4): 577/3600Dice(5): 603/3600Dice(6): 574/3600

3.5.2 石ころなげゲーム:的に当たる数は?

次はたとえば1m× 1m四方の板上に何個も何個も小石を投げつけるゲームのシミュレーションを行うことを考えよう。1回ごとにぶつかった点の詳細な座標 x,yを記録しておく。最後に集計するときその座標から

√x2 + y2 の値を計算しその値が 1m以下であれば数を数える。そして全試行数のなかでそ

の数がどのくらいあったかを計算させる。その数をかく。また回数を増やして同じことを繰り返す。たとえば 4000粒の小石を投げて先の条件計算させることを 1ゲームとする。10ゲームでの平均値を求めてみよう。1ゲームでだいたい 3142個が条件に合致すると期待されるが。図示すると以下のようなことをやっているわけである。

43

Page 44: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

このプログラムは以外と簡単にあっさりと書き下せる。もともとシミュレーションとは物語性が高いものなのでプログラムの書き出しもストーリーにしたがっていけばいいのかもしれない。

class MCpiCalc {public static void main(String args[]) {long Ntotal=4000 ;long sum ;double x,y,r,average ;long game=10 ;long inside ;

sum=0 ;for(int k=0;k<game;k++) {inside = 0 ;for(int i=0;i<Ntotal;i++) {x=Math.random() ;y=Math.random() ;r=Math.sqrt(x*x+y*y) ;if(r<=1.0) inside++ ;

}System.out.println("Game: "+k+" = "+inside) ;sum += inside ;

}average=(double)sum/game ;System.out.println() ;System.out.println("Average over "+game+" games = "+average) ;

}}

結果は以下が 1例である。piを求めるのにはシミュレーションはあまりよい方法とはいえないかもしれない。

Game: 0 = 3152Game: 1 = 3105Game: 2 = 3109Game: 3 = 3141Game: 4 = 3178Game: 5 = 3172Game: 6 = 3109Game: 7 = 3162

44

Page 45: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

Game: 8 = 3102Game: 9 = 3165

Average over 10 games = 3139.5

3.5.3 ゲームの理論:囚人のジレンマ

3.6 課題

45

Page 46: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

4 アプレット(Applet)を使って図形を描く本来であればここから Javaの真骨頂で面白くなってくるところ。残念ながら時間があまりない。図

形はAppletviewerか Netscape(IEでも)で表示可能なようにするためAppletという概念を利用して描く。Javaで Appletプログラムを作りその結果を Appletviewerか Netscapeで鑑賞するやり方もここで学ぶ。とくに注意してほしいのはAppletをWebブラウザで表示するにはAppletを記述する Java

プログラムとAppletをWebブラウザに載せる方法を記述するWebの htmlファイルの2つが必要であるということである。 

4.1 画面構成基本的にスクリーン 2次元平面を使って図形を描くのであるから、まずその基本となる画面構成を理

解しよう。以下に示すのがその画面座標である。

y

x[x,y]=(0,0)

(width,height)

widthheig

ht

図中x座標末端を意味する widthやy座標末端の heightの値は Javaプログラムにおいては以下に例示するが、Appletクラスのメソッド initで指定する。 

4.2 Class Graphicsを使った基本作図4.2.1 基本図形要素描出 appletプログラム例

以下の Javaプログラムを例示することにより基本図形作図プログラミングを見ていこう。Javaプログラム(DisplayShape.java)

import java.applet.Applet ;import java.awt.* ;public class DisplayShape extends java.applet.Applet {

public void init() {resize(600,600) ;

}public void paint(Graphics gobj) {

int r,g,b ;Color clr,fg,bg ;clr = Color.black ; //new Color(r,g,b) ;gobj.setColor(clr) ;

int x,y,rectWidth,rectHeight ;// 直線  (drawLine)x=10;y=140;rectWidth=140;rectHeight=-140;gobj.drawLine(x,y,x+rectWidth,y+rectHeight) ;// 多直線 (drawPolyline)

46

Page 47: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

int x2point[] = new int[6] ;int y2point[] = new int[6] ;double [] degAngle = {18.0,90.0,162.0,234.0,306.0} ;double starRadius=75.0 ;int jban[]={2,0,3,1,4} ;int xoffset=75,yoffset=225;for(int i=0;i<5;i++) {

x2point[jban[i]]=(int)(starRadius*Math.cos(Math.toRadians(degAngle[i]))+0.5)+xoffset ;y2point[jban[i]]=(int)(starRadius*Math.sin(Math.toRadians(degAngle[i]))+0.5)+yoffset ;

}x2point[5]=x2point[0] ;y2point[5]=y2point[0] ;gobj.drawPolyline(x2point,y2point,x2point.length) ;// 塗りつぶし多角形 (fillPolygon)int xPoints[] = {70,20,35,120,150} ;int yPoints[] = {310,340,430,430,390} ;gobj.fillPolygon(xPoints,yPoints,xPoints.length) ;// 多角形 (drawPolygon)int x1Points[]={75,15,135} ;int y1Points[]={472,576,576} ;gobj.drawPolygon(x1Points,y1Points,x1Points.length) ;)// 円あるいは楕円 (drawOval)x=160;y=10;rectWidth=130;rectHeight=130;gobj.drawOval(x,y,rectWidth,rectHeight) ;//塗りつぶし円あるいは楕円(fillOval)y=180;rectHeight=90;gobj.fillOval(x,y,rectWidth,rectHeight) ;//角丸四角(drawRoundRec)y=320;rectHeight=110;int arcWidth,arcHeight ;arcWidth=30;arcHeight=30;gobj.drawRoundRect(x,y,rectWidth,rectHeight,arcWidth,arcHeight) ;//塗りつぶし角丸四角(fillRoundRec)x=180;y=460;rectWidth=90;rectHeight=130;arcWidth=50;arcHeight=50;gobj.fillRoundRect(x,y,rectWidth,rectHeight,arcWidth,arcHeight);//四角(fillRect、drawRect、draw3DRect、fill3DRect)bg = Color.lightGray ;fg = Color.black ;for(int i=0;i<4;i++) {

x=310+i*10 ;y=30-i*10+i*150 ;rectWidth=130-i*20 ;rectHeight=90+i*20 ;if(rectHeight > 150) rectHeight=145 ;if(i==0) {

gobj.fillRect(x,y,rectWidth,rectHeight) ;} else if (i==1) {

gobj.drawRect(x,y,rectWidth,rectHeight) ;} else if (i==2) {

gobj.setColor(bg) ;gobj.draw3DRect(x,y,rectWidth,rectHeight,true) ;

} else {

47

Page 48: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

gobj.setColor(bg) ;gobj.fill3DRect(x,y,rectWidth,rectHeight,true) ;

}}//弧(drawArc)gobj.setColor(fg) ;int arcRadius=120 ;x=460-arcRadius;y=140-arcRadius;rectWidth=arcRadius*2;rectHeight=rectWidth;int startAngle, extendAngle ;startAngle=30 ;extendAngle=60 ;gobj.drawArc(x,y,rectWidth,rectHeight,startAngle,extendAngle) ;//塗りつぶし弧(fillArc)arcRadius=70;rectWidth=arcRadius*2-10;rectHeight=rectWidth+20;x=525-rectWidth/2 ;y=225-rectHeight/2 ;startAngle=120 ;extendAngle=60;gobj.fillArc(x,y,rectWidth,rectHeight,startAngle,extendAngle) ;

}}

この javaプログラムを使って appletを作り上げるのだが、この appletを appletviewerかWebブラウザに表示させるには applet表示用 htmlファイルを作成しなければならない。DisplayShape.htm

<html><body>Applet Test:<p><P><applet code="DisplayShape.class" width=600 height=700></applet></body></html>

これら2つのファイルを以下の手順で実行させた。

[id@machine~]# javac DisplayShape.java

[id@machine~]# appletviewer DisplayShape.htm

この結果を以下に示す。

48

Page 49: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

この図は appletに作図するクラス java.awt.Graphicsのほとんどの基本作図要素を網羅している。以下の表に上図内の各要素を作図するのに必要な class Graphicsのメソッドを示している。詳しくは http://java.sun.com/j2se/1.4.1/docs/api/java/awt/Graphics.htmlを参照のこと。

drawLine drawOval fillRect drawArc

drawPolyline fillOval drawRect fillArc

fillPolygon drawRoundRect draw3DRect

drawPolygon fillRoundRect fill3DRect

4.2.2 DisplayShape.javaの分析 I Appletクラスの継承、Graphicsクラスの具体化

• import java.applet.Applet ;

import java.awt.* ;

java.appletに属する Appletクラス(appletを作成するため、また applet内に配置したコミュニケーションツール処理のためのクラスライブラリ)と java.awtに属するすべてのクラス(ユーザインターフェース、グラフィックスおよびイメージ描画に必要なクラスライブラリ)を用いることを宣言する。

• public class DisplayShape extends java.applet.Applet {public void init() {

resize(600,600) ;}public void paint(Graphics gobj) {

より Appletクラスを継承して自分自身でDisplayShape という独自 appletを定義する。Appletクラスにはさまざまなメソッドが用意されているがこのDisplayShapeではとくにメソッド initとメソッド paintを改編している。initでは appletのサイズ(グラフ表示座標範囲)を設定、paintメソッドは java.awt.Graphicsクラスを利用してイメージや図形を記述させるようにしている。

49

Page 50: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

• public void paint(Graphics gobj) {int r,g,b ;Color clr,fg,bg ;clr = Color.black ; //new Color(r,g,b) ;gobj.setColor(clr) ;

paintではまずGraphicsクラスを具体化(オブジェクト化)したクラス変数 gobjを使う。Graphicsクラス定義の変数、定数、メソッドをオブジェクト gobjを通して利用していく。したがって基本作図要素描画メソッドを呼び出すときには接頭辞”gobj.”をその名前のまえに必ずおく。次にColorクラスをオブジェクト化し変数名を clr,fg,bgで宣言。clrには Colorクラス変数を利用して黒を登録。Graphicsのメソッド setColorで現在の前景色を黒に設定。

4.2.3 DisplayShape.javaの分析 II Graphicsクラスの基本作画メソッド

直線 drawLine(x1,y1,x2,y2)

四角 drawRect,fillRect,draw3DRect,fill3DRect(x,y,width,height,{boolian raised})

左上コーナーの座標と四角の幅(width)、高さ(height)を指定。draw3DRect、fill3DRectは trueか falseでエンボスが表面から盛り上がるか、下がるかを指定。

楕円、円(oval)drawOval,fillOval(x,y,width,height)

4つのパラメータは xxxxRectの最初の4つのパラメータと同様。

角丸四角 drawRoundRect,RoundRect(x,y,width,height,arcWidth,arcHeight)

最初の4つのパラメータ(引数)指定は通常の四角を描く場合と同じ。それに以下の図に示した角の曲りを指定するパラメータを加える。

arcHeight arcWidth

50

Page 51: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

多角形、ポリゴン drawPolygon,fillPolygon(int[] xPoints, int[] yPoint,ints nPoints)

各頂点の座標を配列形式でx、y個々に設定、最後にポイント数を指定。(x[1],y[1])

(x[5],y[5]) NP=6

円あるいは楕円弧(arc)drawArc,fillArc(x,y,width,height,startAngle,extend)

弧の中心は x,yとwidth、heightで指定さえる四角の中心になる。startAngle、extendは弧の初期角度と角度幅。ともに度(degree)で指定。初期角度=0°とは時計 3時を意味する。そして角度は反時計周りで増えていく。

width

heig

ht

startAng

extend

θ0

4.2.4 色指定

4.2.1 節の例題DisplayShape.javaにも多少例が載っているが線、面の色指定について見ておこう。基本となるのは Colorクラスをオブジェクト化するために変数を用意することである。例えばColor clr,lineclr,areaclrなどと指定する。そしてそれらの変数に色値を設定する。その方法は2つある。

1. Colorクラスにすでにクラス変数として指定されている規定値を利用すること。

clr=Color.black ;   lineclr=Color.red ;

areaclr=Color.lightGray ;

2. 自分で赤、緑、青の配合を考えて色を作りだすこと。

Color clr ;int red,green,blue ;red=125;green=200 ;blue=64 ;

clr= new Color(red,gree,blue) ;

各色値は 0から 255まで。

そしてその後に setColorメソッドを呼び出すことで次に再び setColorメソッドが呼ばれるまであらゆるグラフィックス操作の色は現状の指定値を元におこなわれる。

public void paint(Graphics g) {int r=200,g=100,b=120 ;Color clr,fg,bg ;clr = new Color(r,g,b) ;g.setColor(clr) ;

51

Page 52: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

クラス Colorについてはhttp://java.sun.com/j2se/1.4.1/docs/api/java/awt/Color.html

を参照のこと。  

4.2.5 文字列

Graphicsクラスとして appletに文字列を表示するのも他の基本図形描画と変わりない。しかし文字列は描画の前に色(設定しなければそれ以前に指定されたもの)、フォント(同様)、サイズ(同様)、あるいはスタイル(同様)を設定しなければならない。つまりテキストの描画は以下の drawStringメソッドで行われるのだが、そのフォント、大きさ、色、スタイルはその時点での値を採用するということである。

drawString(String, int x, int y)

さらにテキストの開始点を x,yで指定するのだが、この y値は以下の図でいうと Baselineを基準に指定しなければならない。したがって下部にもまだ成分が残っている文字(gとか y)についての配慮も必要である。上部も大文字に対しても十分余裕をみてスペースを確保しなければならない。

HjA scender L ine

B aseL ine

Descender L ine

例:DisplayString.java

import java.awt.* ;public class DisplayString extends java.applet.Applet {

public void init() {resize(400,200) ;

}public void paint(Graphics g) {

Font f = new Font("TimesRoman",Font.PLAIN,14) ;g.setFont(f) ;g.drawString("The quick brown fox jumps over the lazy dogs back",10,100) ;

}}

その htmlファイル:DisplayString.htm

<html><body><applet code="DisplayString.class" width=400 height=200></applet></body></html>

実行結果は

52

Page 53: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

4.2.6 Fontについて

前節で文字列表示についてもっとも一般的な drawStringメソッドを使った方法を概説した。本節ではそのときちょっと触れた文字表示の設定(フォント、スタイル、サイズ)について触れてみたい。Graphicsクラスのメソッドに setFontというメソッドがあり以後に利用される文字フォントの設定をする。文字フォントは Fontクラスの変数として実現される。Fontクラスの実現は Fontというクラスコンストラクタによりなされるが、そのために必要なパラメータはフォントの名前、スタイル、サイズである。具体的には前節に例示した DisplayString.javaの以下の部分を参照してほしい。Fontクラスコンストラクタの各パラメータのどれがどの意味をもっているかは明白であろう。

public void paint(Graphics g) {Font f = new Font("TimesRoman",Font.PLAIN,14) ;g.setFont(f) ;

Fontコンストラクタは Font(String name, int style, int size) ;の形で設定される。

name フォント名で実際のフォントセットの名前かDialog,DialogInput,Monospaced,Serif,SanSerif,Symbol

で示されるいわゆる論理名称を利用する。フォントセット名には以下の例で示すようなTimesRoman,Helvetica,courier

などがある。

style スタイルは Font.PLAIN,Font.ITALIC,Font.BOLDで指定。Font.BOLD|Font.ITALIC指定もできる。

size ポイントサイズ。整数。

以下に setFont/drawStringのプログラム例 DisplayFonts.javaとその実行例を示す。

import java.awt.* ;public class DisplayFonts extends java.applet.Applet {

public void init() {resize(600,400) ;

}public void paint(Graphics g) {

Font f1=g.getFont() ;String s = f1.getName()+" "+f1.getSize()+" (Default)" ;g.drawString(s,10,10) ;Font f2 = new Font("TimesRoman",Font.PLAIN,10) ;

53

Page 54: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

s = f2.getName()+" "+f2.getSize() ;g.setFont(f2) ;g.drawString(s,10,100) ;Font f3 = new Font("Helvetica",Font.PLAIN,12) ;s = f3.getName()+" "+f3.getSize() ;g.setFont(f3) ;g.drawString(s,10,150) ;Font f4 = new Font("courier",Font.PLAIN,14) ;s = f4.getName()+" "+f4.getSize() ;g.setFont(f4) ;g.drawString(s,10,250) ;Font f5 = new Font("DialogInput",Font.PLAIN,36) ;s = f5.getName()+" "+f5.getSize() ;g.setFont(f5) ;g.drawString(s,10,300) ;

}}

4.3 参考Webページ今まで出てきたクラスに関する解説 webサイトを以下に示そう。

1. Appletクラスはhttp://java.sun.com/products/jdk/1.2/docs/api/java/applet/Applet.html

2. Graphicsクラスはhttp://java.sun.com/products/jdk/1.2/docs/api/java/awt/Graphics.html

3. Colorクラスは http://java.sun.com/products/jdk/1.2/docs/api/java/awt/Color.html

4. Fontクラスは http://java.sun.com/products/jdk/1.2/docs/api/java/awt/Font.html

5. なおさらに進んだ基本(2次元)図形描画、処理クラスも存在する。それはGraphics2Dクラスであり、http://java.sun.com/products/jdk/1.2/docs/api/java/awt/Graphics2D.html

54

Page 55: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

4.4 課題1. 以下のような図を作ってください。画面 (width x height) = 600 x 600です。

2. 以下のような図を作ってください。画面 (width x height) = 600 x 600です。外枠の四角の大きさは 576x576、中の四角の辺の長さはバランスをとって適当でいいです。

55

Page 56: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

3. 以下のような図を作ってください。画面 (width x height) = 600 x 600です。上記課題パターンが縦横 8個づつ並んでいます。

56

Page 57: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

4. 以下のプログラムは円を drawLineのみで描くプログラムである。よく読んでほしい。Graphicsクラスのメソッドはすべて整数は int、実数は floatなので double→ float変換(cast)や、実定数の与え方(1.0f、0.25fなど)に注意を払ってほしい。またMathクラスの数学関数(メソッド)や定数 (Math.PI)などもみな doubleなのでその結果を利用する場合も castしなければならない。

DsiplayCircle.java

import java.applet.Applet ;import java.awt.* ;

public class DisplayCircle extends Applet {float PI=(float)Math.PI ;int winWidth=300, winHeight=300 ;float circRadius=100.0f ;public void init() {

setBackground(Color.lightGray) ;setForeground(Color.red) ;resize(winWidth,winHeight) ;

}public void paint(Graphics g) {

float r=circRadius,delta,theta,x0,y0,x1,y1 ;float xc,yc ;int nPoints =200 ;xc=winWidth/2 ;yc=winHeight/2 ;x0=0.0f ;y0=0.0f ;for(int k=0;k<nPoints;k++) {

if(k==0) {theta=0.0f ;

x0=r*(float)Math.cos(theta)+xc ;y0=r*(float)Math.sin(theta)+yc ;

}theta=2.0f*PI*(float)(k+1)/(float)nPoints ;x1=r*(float)Math.cos(theta)+xc ;y1=r*(float)Math.sin(theta)+yc ;g.drawLine((int)x0,(int)y0,(int)x1,(int)y1) ;x0=x1;y0=y1;

}}

}

この結果は以下のようになる。

このプログラムを熟読してください。そして以下に示すプログラムを作ってください。

57

Page 58: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

DisplayLeaves.java 実数 a=固定(circRadius)にして、半径 rを theta(θ)とともにを以下のように変える.

r = a sin (jθ/i)

ここで i,jは整定数、aは実定数(circRaius)。0 ≤ θ ≤ 2π。つまり rは θとともに変化する。i,jをいくつか変えたサンプル出力を以下に示す。

プログラムは 1 ≤ i ≤ 5, 1 ≤ j ≤ 5すべてに完璧に対応できるようにしてください。また最後の文字列は以下のようにコーディングしました。

g.drawString("Leaves i= "+i+" j= "+j,110,275) ;

なおできれば以下のような一覧表を作成してみてください(これは必ずしも必須ではない、余裕のある人は挑戦してください)。文字の位置は移動しました。

58

Page 59: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

5. 以前みたセルラーオートマトンの一般化したものを作成します。ある与えられた正の整数数 init(0から 255)を 2進数で表現するプログラムをまず作る。二進数とは整数を

init = n7 · 27(128) + n6 · 26(64) + n5 · 25 + · · · + n1 · 21(2) + n0 · 20(1)

に分解し係数 n7から n0まで求め、これらを n7n6 · · ·n1n0と並べて表すことである。各係数は 0か 1のみをとる。たとえば 78は 01001110、170は 10101010となる。そしてこの係数をプリントするとともに整数配列 bitpat[8]に格納する。bitpat[0]は n0、bitpat[1]は n1 といったように。

さてここにパターンとして 11011000101...といったような 1と 0のみの数字列が並んでいるとする。そしてこのパターンがある法則で次の世代のパターンを作りだしていくものとする。その法則はパターン中のある数字の次の世代はその数字と左右の数字の 3つで決まるものとする。1か 0しかない数字が 3個あるので組み合わせとして全部で 23 = 8個の法則を導入すればいい。つまり111→?110→?101→?100→?011→?010→?001→?000→?である。この数字の並びを 2進数は 10進数で言うと上から 7,6,5,4,3,2,1,0である。この法則は先に initで与えた 0から 255の数字の 2進数の係数で決めることにする。つまり配列 bitpat[i]が i番目のパターンの次世代を決めるとする。たとえば init=250は 11111010なので 111→ 1110→ 1101→ 1100→ 1011→ 1010→ 0001→ 1000→ 0となる。いま 61個の 1、0の羅列があり最初は真中の 30番目が 1でそれ以外は全部 0となっているとする。そして initに適当な値をいれて法則を与え 60ステップ(世代)ほど繰り返した場合の各数字のパターン変化を観測してプリントしたい。そのようなプログラムを作ってください。望むらくは 1は*、0は空白に変換してプリントするのがよい。たとえば init=22だといかの図のようになる。

59

Page 60: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

つづいてこのパターンを appletで描き小さな四角 5*5程度の大きさで表すようにしてください。そのとき数字1ではたとえば四角の色は赤、0はグレーとするといった工夫をします。また数字の羅列も 61から 121程度に拡大しステップ数も 100ぐらいにしてください。以下に init=22、init=45のパターンを示します。四角の大きさは 8*8、数字の羅列は 81、世代交代は 60ステップです。

60

Page 61: Java プログラミング入門 - Tokyo Metropolitan Universityンをjava と呼ぶ(上記2 行目参照)。言い換えるとjava というアプリケーションプログラムは仮想マシーンと呼ばれるものでありそれは

6. 壁紙パターンを作りたい。ひとつの変数(正数)を任意にとることによって自由にパターンを作り出せるプログラムを作成したい。そのため以下の手順を考えた。

整変数 sideに値をセットfor i ← 0 to 99

y = i× side/100

for j ← 0 to 99

x = j× side/100

c=整数(x^2+y^2)if cが偶数色をマゼンタ(magenta)にセット

     5× 5程度の塗りつぶし四角を (j,i)ポジションに対応するところに描画(fillRect)else

色を明るいグレイ(lightGray)にセット     5× 5程度の塗りつぶし四角を (j,i)ポジションに対応するところに描画(fillRect)

このレシピにしたがって壁紙パターンを作り出す Javaプログラムを作成しなさい。

実際の (j,i)の四角を描く場合図中赤点の位置の計算に注意すること。正方形の幅は5程度が見栄えがするが変数として異なる値をとれるように考慮すること。

以下にいくつか sideの値を変えて作ったパターンを示す。sideの値は左から 82、187、357である。その他さまざまな値をとって気に入ったパターンを選んでください。そのときの sideの値を知らせてください。

61