プログラミング/2

出典: CourseWiki

目次

Javaプログラムの構造

// 画面に Hello, World を表示する
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

public class Hello は「これから Hello というクラスの定義を 行います」という意味です.今のところはクラスとはプログラムのような ものだと思って下さい.Javaでは,クラス名は大文字で始める習慣になって います.クラスについての詳しいことは後日やります.

public class Hello {
    // ここにはHelloクラスの中身を書きます
}

public static void main(String[] args) は「これから main というメソッド の定義を行います」という意味です.メソッドは,プログラムの動作を 定義するためのものだと思って下さい.これも詳しいことは後日やります. Javaのプログラムは必ず main メソッドから実行されるという約束になっています.

public class Hello {
    public static void main(String[] args) {
         // ここには mainメソッドの中身を書きます
    }
}

System.out.println(..) は文字列を表示して改行する命令です.これの親戚として,System.out.print(..) があります.これは表示しますが,最後に改行しません.

このため,以下のように書いても同じように表示されます.あたりまえのようですが,プログラムはプログラムに書かれている順(上から下)に実行される ことに注意して下さい.このように,上から下に順番に実行することは逐次処理と呼ばれています.

// 画面に Hello, World を表示する (その2)
public class Hello {
    public static void main(String[] args) {
        System.out.print("Hello, ");
        System.out.println("World");
    }
}

行の終りにあるセミコロン(;)は,命令と命令を分けるための大切なものです.入れ忘れないようにしましょう.

インデント(字下げ)

Javaのプログラムですが,行の頭に妙な空白が入っていることに気が 付きましたか? この先頭の空白の部分のことをインデント(または字下げ))と言います.Java言語自体はインデントの大きさは気にしません.また,キーワードや文字列の途中以外ならば自由に改行できるので,書こうと思えば,

public class 
Hello {
public static void 
main(String[] args) {
System.out.println(
"Hello, World");
}}

のようにも書けますが,これでは見にくいのできちんとインデントして下さい.インデントは,{ と } の対応を分かりやすくして,プログラムの構造の理解を助ける働きがあります.

インデントは以下のルールに従って下さい.

  • { を書いたら,次の行から字下げを1段深くする.
  • } は,対応する { の行の字下げの幅と合わせる(1段浅くする).

インデントを入れるには通常TABキーを使います.

Eclipse では { を入力すると自動的に対応する } が入力され,カーソルが適切な位置に飛ぶようになっています.

プログラムを修正しているとインデントが乱れることがあります. インデントが乱れると,プログラムを書いている人も読む人も混乱するので,インデントを修正するようにしましょう. レポートのプログラムでインデントがおかしい場合は減点の対象にしますので.注意して下さい.

Eclipseでは乱れてしまったインデントも簡単に修正できます(領域を選択してSource->Correct Indentation).

演算

コンピュータなんだから,計算させてみましょう.

Javaの演算子(一部)
演算Javaでの表記
加算+1+2
減算-1-2
乗算*4*10
除算/20/4
剰余%20%3(20を3で割った余り)

括弧も使うことができます.

// 計算してみよう
public class Calc {
    public static void main(String[] args) {
        System.out.print("1 + 10 = ");
        System.out.println(1 + 10);
        System.out.print("15 * (10 - 30) = ");
        System.out.println(15 * (10 - 30));
    }
}

Eclipseでこのプログラムを入力するには,プロジェクトを選択している状態で File->New->Class を選び,Calc クラスを作ります

"二重引用符(ダブルクォーテーション)"で囲まれたところは文字列(string)で,そのまま表示されます. 5行目の 1 + 10 は囲まれていないので,式(expression)として扱われます.

また,文字列に含まれていない部分の数値 (1, 10, 15など) は,定数(constant)と呼ばれます. その名の通り,値が変化しない数です.

変数

違う計算をさせるたびに,いちいちソースプログラムを修正してコンパ イルするのは面倒ですね.次はキーボードから計算する値を入力できるよう にしましょう.

キーボードからの入力の前に,まず値を覚えておくための仕掛け (変数(variable))について説明します.

プログラミング言語の変数とは,「何かを入れる」ための箱です.箱(変 数)に入れたら,「その中身を見たり」,「それを使って計算したり」する ことができます.後から箱の中身を変化させることもできます.

プログラミングの世界では,変数に何かを入れることを代入(assignment)と言 います.

変数には型(type)があります.型は,その変数に入れることができる中身の種類を表します.Javaでは,基本の型には整数型(int),実数型(float, double)等があります.整数型の変数に,実数を入れたりすることはできません.

Javaの基本型(一部)
種別大きさ定数の表記法値の範囲
整数int32ビット10,-499-2147483648〜2147483647
倍長整数long64ビット10L,-499L-9223372036854775808 〜 9223372036854775807
実数float32ビット3.1415f,1.3e32f1.4e-45(最小) 〜 3.4028235e38(最大)

(それぞれ1.4\times10^{-45}, 3.4028235\times 10^{38}という意味)

倍長実数double64ビット3.1415,1.3e-324.9e-324(最小) 〜 1.7976931348623157e308(最大)

変数に型があるのと同様に,定数にも型があります.上の表の「定数の表記法」で示した書き方で書くと,その型の定数になります(10と書けばint型の定数,10.5と書けばdouble型の定数).

計算機の中では数値は2進法で表されています.10進法の各桁は0〜9の10通 りありましたが,2進法では,各桁は0か1の2通りしかありません.int型は2進 数で32桁(32ビット)の値を,long型では64桁(64ビット)の値を格納できます. このため,int型よりもlong型の方が表せる値の範囲が広くなります.

プログラムを書くときは,変数に入る可能性がある値の範囲を予想して変数の型を選ぶ(int? long?等)必要があります.

なお,floatやdoubleは有限の精度しかないので,プログラムで実数を扱うには注意が必要です. 10進数では切りの良い数値も,2進数では循環小数になる場合が多く,近似値としてしか扱えない場合が多々あります (例えば10進数の0.1という値は循環小数になるため有限桁数の2進数では正確に表せません). float型よりもdouble型の方がビット数が多いので精度が高い計算ができます.

変数名

変数の名前を変数名と言います.言ってみれば箱の名前です. 変数には分かりやすい名前をつけましょう.良い変数名をつけるのも重要な技術です. (a, b, c ではなく,height, width, count のように).

Javaでは,変数名は小文字から始めることが推奨されています.

また,一般に変数名 i, j, k, l, m, n は整数型の変数に使う慣習があるので,従っておきましょう (FORTRAN の規則に由来).

変数の作り方・代入と参照

変数を作るには,int a; のように,型名 変数名; と書きます.

変数に値を入れる(代入)するには,変数名 = 値; と書きます. の部分には,を書くことができます.ですから,一般的には 変数名 = 式; です.

0001:// 変数の例
0002:public class Hensuu {
0003:    public static void main(String[] args) {
0004:        int a;                  // 変数aをつくります
0005:        int b;                  // 変数bをつくります
0006:
0007:        a = 10;                 // 変数aに定数10を代入
0008:        b = 20;                 // 変数bに定数20を代入
0009:        // 変数resultをつくって,a+bの結果を代入
0010:        int result = a + b;
0011:
0012:        // 結果の表示.System.out.printlnは文字列だけでなく
0013:        // int型の変数も表示できます.
0014:        System.out.println(result);
0015:    }
0016:}
0017:

10行目のように,変数を作って同時に値を入れることもできます. このとき,= の右側にある式を初期化式と呼びます.

また,(同じ型ならば) int a, b; のように複数の変数を同時に作ることもできます.

なお,計算や表示のために変数の値を使うことを,変数を参照(refer)すると言います.

変数は,作っただけでは(一度も代入されていなければ)値がなにも入っていません.値が入っていない変数は参照することはできません.

整数型の変数 a
値はまだ入っていない状態

値 1253 が代入されている状態

演習(double型)

  1. double型の変数を用いて,30.5 * 20.3 を計算せよ.
  2. double x = 5 / 2; として x の値を表示してみよ.

演習(double型)の解答例

定数

5 / 2 の結果は何故か 2.5 にはならず,2 になってしまったはずです.これはJavaの演算の規則によるものです.

まず,プログラム中の 5 や 2 のような数を 定数と言います.その名の通り,変数と違って値が変化しない数ですね.

変数に型があるのと同様に,定数にも型があります. Javaプログラムの中で,上の表の「定数の表記法」で示した書き方で書くと, その型の定数として扱われます(10と書けばint型の定数,10.5と書けばdouble型の定数).

Javaでは,int型同士の演算の結果は int 型になるという約束があります.5 / 2 は 2.5 という値ですが,Java ではint型で計算されるので,切り捨てられて2になってしまうのです.

これを避けるためには,5.0 / 2.0 と書きます.5.0 のように小数点を付けると,double 型 (実数型)と見なされるので(上の表参照),結果は 2.5 になるのです.

では,5.0 / 2 と書いたらどうなるでしょうか? Javaでは,演算するときに以下の変換規則があります.

Javaの変換規則
  • 演算数のどちらかが double の場合,もう片方は double に変換される.
  • そうでない場合,演算数のどちらかが float の場合,もう片方は float に変換される.
  • そうでない場合,演算数のどちらかが long の場合,もう片方は long に変換される.

これに従うと,5.0 / 2 は,最初の規則に当てはまることがわかります.この場合,int 型の 2 が double 型の 2.0 に変換されて,結果的に 5.0 / 2.0 が計算されます.

キーボードからの入力

Javaでキーボードからの入力を正式なやり方で行うには,まだ説明していないちょっとややこしいコトをいくつか説明しないといけないので,ここでは簡単に行うための補助的な仕掛けを使います.

  • まず,このページ から Keyboard.java を入手します.
  • 次に javac で Keyboard.java をコンパイルしてください(Eclipseの場合は不要).
javac Keyboard.java
  • これで Keyboard.class ができるはずです.

次のプログラムは,Keyboard.class がないと動きません.

Keyboard.intValue() は,キーボードから整数を入力するための命令です.プログラムの実行がKeyboard.intValue()に到達すると,数字が入力されてEnterキーが押されるまでプログラムの実行は停止します.

// Keyboardを使った例
public class Chouhoukei {
    public static void main(String[] args) {
        int a;
        int b;
 
        System.out.print("一辺の長さを入力して下さい: ");
        // キーボードから数値を入力するまで待ち,その値を変数aに入れる)
        a = Keyboard.intValue();
 
        System.out.print("もう一辺の長さを入力して下さい: ");
        b = Keyboard.intValue();
 
        int menseki = a * b;
 
        System.out.print("面積は ");
        System.out.print(menseki);
        System.out.println(" です");
    }
}

数学では y = f(x) のように書くと,y は関数f(x)の値に等しいという意味ですが,プログラミング言語では,a = Keyboard.intValue() は,Keyboard.intValue() のを a に代入するという意味になります.

Keyboard.intValue() は,(キーボードから入力された値を持つ)式と考えて下さい.a = Keyboard.intValue() を実行するとき,コンピュータは次のように動作します.

  • まず,Keyboard.intValue()を実行します.コンピュータはキーボードからの入力待ち状態になります.
  • キーボードから例えば123と入力すれば,Keyboard.intValue()の実行は終了します.Keyboard.intValue()は123という値を返します.
  • その値(123)を変数 a に代入します.

プログラミングの世界の言葉を使うと,「Keyboard.intValue() はキーボードから入力された値を返す」等と表現します.

同様に Keyboard.doubleValue() は,キーボードからdouble型(倍長実数)の数を入力するための命令です.

double jissu = Keyboard.doubleValue();

のように使います.

演習(円の面積・球の体積)

半径rを入力すると,円の面積(πr2)を求めるプログラムCircleを作れ.円周率は3.14としてよい. 同時に球の体積 (\frac{4}{3}\pi r^3) も求めよ.

  • ヒント1.実数を扱うので,double型を用いる.
  • ヒント2.2乗するためには r * r で良い.
  • ヒント3. 結果は,必ず一度手で計算した結果と合致するかを確かめること.

演習(円の面積・球の体積)の解答例

文字列の連結

System.out.print("面積は ");
System.out.print(menseki);
System.out.println(" です");

と書く代わりに,

System.out.println("面積は " + menseki + " です");

と,+ を使って書くことができます.

条件分岐(if文)

いままでのプログラムは,上から下に一直線に実行されるもの (逐次処理)ばかりでした.これでは単純なことしかできないので,条件 によって実行することを変える方法を学びましょう.

例題として,整数を入力して,奇数か偶数かを判定するプログラムを つくってみましょう.与えられた数を2で割った余りが0なら偶数,そうで なければ奇数です.

こういうとき,Javaではこんな風に書きます.if と else のところに注目してください.

// 奇数か偶数かを判定
public class EvenOrOdd {
    public static void main(String[] arg) {
        System.out.print("数値を入力してください: ");
        int number = Keyboard.intValue();
        // number を 2 で割った余り(number % 2) が 0 に等しいか判定
        if (number % 2 == 0) {
            System.out.println("偶数です");
        } else {
            System.out.println("奇数です");
        }
    }
}

if文は,「ある条件が成り立ったときにだけ,ある処理をす る」ための構文です.

// if文の書き方
if (条件) {
  条件が成り立ったときに実行する文
} else {
  条件が成り立たなかったときに実行する文
}

else節はなくても構いません.この場合,条件が成り立たないとif文の次の文の実行に進みます.

if (条件) {
  条件が成り立ったときに実行する文
}
// 次の文

次のようなJavaのプログラムは下の図のように実行されます.

処理1;
if (条件) {
  処理2;
  処理3;
} else {
  処理4;
  処理5;
}
処理6;


このような図をフローチャートと呼びます

真偽式

条件の部分には真偽式(boolean expression)を書きます.真偽式とは,値として true (真,成立) か false (偽,不成立)かを返すような式のことです.Javaでは真偽式として次のようなものを使うことができます.

演算子意味
式1 == 式2等しい(式1と式2の値が等しいならば true,そうでなければ false)a == 0
式1 != 式2等しくない(式1と式2の値が等しくないならば true)a != 1
式1 < 式2小さい(式2より式1の値が小さければ true)a < 10
式1 > 式2大きい(式2より式1の値が大きければ true)10 > b
式1 <= 式2小さいか等しい(式2より式1の値が小さいか等しいならば true)a <= b
式1 >= 式2大きいか等しい(式2より式1の値が大きいか等しいならば true)a >= 3.14
!真偽式否定(真偽式が false ならば true, true ならば false)!(a == 1)
真偽式1 && 真偽式2かつ(真偽式1と真偽式2が両方ともtrueならば true)(1 <= a) && (a <= 2)
真偽式1 || 真偽式2または(真偽式1と真偽式2のどちらかがtrueならばtrue)(a <= 1) || (b == 2)

注意 : 例えば変数 a が 10 から 20 の範囲なら何かをしたい場合, 真偽式として 10 <= a <= 20 と書くのは誤りです. Javaでは,10 <= a && a <= 20 と書かないといけません.

if文のネスト

整数を1つ入力し,それが0ならば「0」,正ならば「正」,負ならば「負」 と表示するプログラムを考えてみましょう.

if文の中に,さらにif文を書くことができます. プログラミング言語では,このように入れ子構造にすることをネスト(nest)といいます.

// 0か正か負かを判定
public class ZeroPlusMinus1 {
    public static void main(String[] arg) {
        System.out.println("数値を入力してください: ");
        int number = Keyboard.intValue();
 
        if (number == 0) {
            // ここは number が 0 に等しいときに実行される
            System.out.println("0です");
        } else {
            // ここは number が 0 に等しくないときに実行される
            if (number > 0) {
                System.out.println("正です");
            } else {
                System.out.println("負です");
            }
            // ここが最初の else の終わり!
        }
    }
}

このプログラムはこんな風にも書けます. こちらの書き方の方が分かりやすいので良いとされています.

// 0か正か負かを判定 (別バージョン)
public class ZeroPlusMinus2 {
    public static void main(String[] arg) {
        System.out.println("数値を入力してください: ");
        int number = Keyboard.intValue();
 
        if (number == 0) {
            System.out.println("0です");
        } else if (number > 0) {
            System.out.println("正です");
        } else {
            System.out.println("負です");
        }
    }
}

注意

以下のようなプログラムはコンパイルエラー (iが初期化されていない可能性がある) になります.

int i;
if (条件) {
  i = 0;
}
System.out.println(i);

これは,変数 i に代入されない可能性があるにも関わらず,System.out.printlnでiの値を使おうとしているからです. 逆に言うと,変数は値を使う前に必ず値が代入されている必要があるということです.

同様に,次のプログラムもコンパイルエラーになります.

// jの値によってiに1か-1をセットする
int i;
if (j >= 0) {
  i = 1;
}
if (j < 0) {
  i = -1;
}
System.out.println(i);

2つのif文のどちらかが必ず実行されるはずなので i を使う前に i に必ず代入されるはずなのですが,コンパイラにはそのことが分からないのでエラーになります.次のようにすれば大丈夫です.

// jの値によってiに1か-1をセットする
int i;
if (j >= 0) {
  i = 1;
} else {
  i = -1;
}
System.out.println(i);

または,

int i = -1;
if (j >= 0) {
  i = 1;
}
System.out.println(i);

課題2-1 (BMI)

BMI(Body Mass Index)指数は,次の式によって与えられる.身長と体重を入力 するとBMI指数を計算し,BMI指数と判定結果を表示するプログラム BMI を書け.

BMI = 体重(kg) / ( 身長(m) * 身長(m) )
20未満痩せている
20以上24未満正常
24以上26.5未満やや肥満
26.5以上肥満

この式は,身長はメートルで与える必要があることに注意すること(160cmなら1.6).

幾つかの入力を試して,きちんと動いていることを示す実行結果を付けること.

課題2-2 (うるう年)

西暦を入力して,それがうるう年かどうか判定するプログラム LeapYear を作成せよ.うるう年は,以下の規則で判定できる.

(1)4で割り切れる年はうるう年である.ただし,(2)100で割り切れる年はうるう年ではない.ただし,(3)400で割り切れる年はうるう年である.

西暦を入力してください: 1996
1996年はうるう年です.

西暦を入力してください: 1900
1900年はうるう年ではありません.

西暦を入力してください: 2000
2000年はうるう年です.

ヒント: 条件(3)に当てはまらなかったら条件(2),条件(2)に当てはまら なかったら条件(1)を判定する.

if (条件3) {
  ....;
} else if (条件2) {
  ....;
} else if (条件1) {
  ....;
} else {
  ....;
}

幾つかの入力を試して,きちんと動いていることを示す実行結果を付けること.

Copyright (C) 2002-2015 Kota Abe, Osaka City University

ナビゲーション