[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理技法(Javaプログラミング)I 第6回

目次
索引

データの入出力(2)

出力の書式

いくつかの整数を1行1行出力するとき、先頭にスペースを入れて、整数を右揃えにすると分かりやすくなります。 また、いくつかの実数を1行1行出力するとき、小数点以下の桁数を統一し、小数点を揃えると分かりやすいです。 このような、出力に関する規則を、 書式 format )または フォーマット とよびます。

Javaには、書式を指定する方法がいくつかありますが、ここで紹介するのは、文

System.out.printf(書式, );

です。 これで、「 」の値を指定された「 書式 」で出力します。

書式の書き方は、最初はパーセント( % )、最後は整数なら d 、実数なら f です。 その間に字数を書きますが、ただの数なら全字数(入りきらない場合は、はみ出す)となり、小数点の後の数なら小数点以下の桁数となります。

また、 0 を書くと、先頭にスペースを入れる代わりに 0 を入れます。 コンマ( , )を書くと、3桁ごとにコンマを入れます。

System.out.printf( ... ); は、最後に改行をしませんので、改行したければ System.out.println(); を実行してください。

FormatTest.java
/*  1*/ class FormatTest { // 書式のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         System.out.printf("%.2f", 1.2345); // 実数を小数点以下2桁で出力
/*  4*/         System.out.println();
/*  5*/         System.out.printf("%8.2f", 1.2345); // 実数を全8字、小数点以下2桁で出力
/*  6*/         System.out.println();
/*  7*/         System.out.printf("%8d", 100); // 整数を全8字で出力
/*  8*/         System.out.println();
/*  9*/         System.out.printf("%08d", 100); // 整数を全8字で出力、先頭に0を入れる
/* 10*/         System.out.println();
/* 11*/         System.out.printf("%,8d", 10000); // 整数を全8字で出力、コンマを入れる
/* 12*/         System.out.println();
/* 13*/     }
/* 14*/ }
コンソール
1.23
    1.23
     100
00000100
  10,000

Completed with exit code: 0

注意: コンソールで等幅でないフォントが使われていると、右揃えや小数点揃えのプログラムを作っても、うまく揃いません。 オンライン・コンパイラーcodiva.ioでは、MacとFirefoxの組合せが等幅でないフォントになっています。


変数と代入文(4)

変数の値の増減

以前、変数に格納されたデータは変更可能であると説明しました。 変数 x にデータ100を格納した後で、101を格納すると、100は上書きされ、 x の値は101になるという話でした。 この仕組みを利用すると、変数の値を増加させることができます。

IncreaseTest.java
/*  1*/ class IncreaseTest { // 増加のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         int x = 100;
/*  4*/         x = x + 1; // 1増加
/*  5*/         System.out.println(x);
/*  6*/     }
/*  7*/ }
コンソール
101

Completed with exit code: 0

このプログラムは、いったん変数 x にデータ100を格納した後、それを1増加させるものです。 4行目は、変数 x に、変数 x の値に1を足したものを格納する代入文です。 x x +1が等しいと言っているわけではありません。 このイメージは次の図のようになります。

変数の値の増加
変数の値の増加

変数の値を1増加させることはよく行われるので、省略形が用意されています。

x = x + 1;

の場合なら、

x++;

と書けます。 変数 y の値を1減少させる、

y = y - 1;

という代入文も、

y--;

と省略できます。

1増加や1減少させるのでなく、いくらか増加やいくらか減少させるための省略形もあります。 以下の表を参照してください。

代入文の省略形
代入文 省略形
変数 = 変数 + ; 変数 += ;
変数 = 変数 - ; 変数 -= ;
変数 = 変数 * ; 変数 *= ;
変数 = 変数 / ; 変数 /= ;
変数 = 変数 % ; 変数 %= ;

以下のプログラムでは、変数 x の値を10増加させて、1増加させています。

IncreaseTest2.java
/*  1*/ class IncreaseTest2 { // 増加のテスト2
/*  2*/     public static void main (String[] args) {
/*  3*/         int x = 100;
/*  4*/         System.out.println(x);
/*  5*/         x += 10; // 10増加
/*  6*/         System.out.println(x);
/*  7*/         x++; // 1増加
/*  8*/         System.out.println(x);
/*  9*/     }
/* 10*/ }
コンソール
100
110
111

Completed with exit code: 0

繰返し文(1)

繰返し文とは

前々回と前回では、条件文を使って、条件が成り立てば何かを実行するというプログラムを書きました。 Javaではこの他に、何かを繰返し実行するというプログラムも書けます。 何かを繰り返す文を、 繰返し文 iteration statement )または ループ文 loop statement )と呼びます。

何かを繰り返す場合、繰返しの回数が分かっている場合と、分かっていない場合があります。 何回繰返すか分かっている場合は、 for文 for statement )を使います。 分かっていない場合は、while文を使います。 (while文は次回説明します。)

for文

以下のプログラムは、10回OKと出力します。

ForTest.java
/*  1*/ class ForTest { // for文のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 0; i < 10; i++) { // 10回繰り返す
/*  5*/             System.out.println("OK");
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK

Completed with exit code: 0

for文の典型的な形式は以下のとおりです。

int i;
...
for (i = 0; i < 回数; i++) {
    ; ...
}

このfor文で、「 回数 」回「 ... が実行されます。 なお、for文を使う前に、変数 i を宣言しておきます。 この i は、 ループ変数 loop variable )と呼ばれます。

for文の実行の流れは以下のとおりです。

for文の実行の流れ
for文の実行の流れ

さて、プログラムForTestがなぜ10回繰り返すのか、不思議だと思います。 この謎は、ループ変数を表示してみれば解決します。

ForTest2.java
/*  1*/ class ForTest2 { // for文のテスト2
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 0; i < 10; i++) { // 0から9まで
/*  5*/             System.out.println(i);
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
0
1
2
3
4
5
6
7
8
9

Completed with exit code: 0

ループ変数が0から9まで変化するので、10回だというわけです。 なので、あとはループ変数が変化する仕組みを理解すれば、完全解決します。

for文の一般的な形式は以下のとおりです。

for (初期化; 条件; 更新) {
    ; ...
}

このfor文で、まず「 初期化 」が実行されます。 そして、「 条件 」が成り立っている間、「 ... と「 更新 」が繰返し実行されます。

for文の「 初期化 」、「 条件 」、「 更新 」を書き換えれば、別のパターンの繰返しもできます。 例えば、ループ変数を1から10まで変化させたければ、ループ変数は初期化で1, 条件で10以下とします。

ForTest3.java
/*  1*/ class ForTest3 { // for文のテスト3
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 1; i <= 10; i++) { // 1から10まで
/*  5*/             System.out.println(i);
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
1
2
3
4
5
6
7
8
9
10

Completed with exit code: 0

10回繰り返すために、ループ変数を0から9まで変化させるfor文と、1から10まで変化させるfor文を紹介しました。 どちらがよいでしょうか。 1から10のほうが分かりやすいかもしれませんが、コンピュータの世界では「0番目」を積極的に使うので、0から9のほうがよいです。

ループ変数

さて、for文を使って

0, 10, 20, 30, 40, 50, 60, 70, 80, 90

と出力するには、どうすればよいでしょうか。 普通にやるなら、数式を使います。 つまり、ループ変数を0から9まで変化させ、それを10倍します。

LoopVariableTest.java
/*  1*/ class LoopVariableTest { // ループ変数のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 0; i < 10; i++) {
/*  5*/             System.out.println(10 * i); // ループ変数の10倍
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
0
10
20
30
40
50
60
70
80
90

Completed with exit code: 0

for文の「 更新 」を書き換えるという方法もあります。 つまり、 i++ で1増加させるのではなく、 i += 10 で10増加させるのです。

LoopVariableTest2.java
/*  1*/ class LoopVariableTest2 { // ループ変数のテスト2
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 0; i < 100; i += 10) { // 10ずつ増加
/*  5*/             System.out.println(i);
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
0
10
20
30
40
50
60
70
80
90

Completed with exit code: 0

これが実数になると注意が必要です。 for文を使って

0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9

と出力する場合、数式を使う(ループ変数を0.1倍する)なら、特に問題は起きません。

LoopVariableTest3.java
/*  1*/ class LoopVariableTest3 { // ループ変数のテスト3
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         for (i = 0; i < 10; i++) {
/*  5*/             System.out.println(0.1 * i); // ループ変数の0.1倍
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9

Completed with exit code: 0

ところが、for文の「 更新 」を書き換える方法だと、11回繰り返すという間違いを犯します。 プログラムでは、「 更新 」で0.1増加させるために、ループ変数を実数型にしています。 プログラムを実行すると、繰返しのたびに実数の誤差が蓄積していき、11回目で成り立たなくなるはずの「 条件 」が成り立ってしまうのです。

LoopVariableTest4.java
/*  1*/ class LoopVariableTest4 { // ループ変数のテスト4
/*  2*/     public static void main (String[] args) {
/*  3*/         double d; // 実数型のループ変数
/*  4*/         for (d = 0.0; d < 1.0; d += 0.1) { // 0.1ずつ増加
/*  5*/             System.out.println(d); // 11回繰り返してしまう
/*  6*/         }
/*  7*/     }
/*  8*/ }
コンソール
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999 // 余分な出力

Completed with exit code: 0

この間違いの教訓は、

ループ変数は整数型に限る。実数型にしてはいけない。

ということです。 ループ変数は、慣習的に i , j , k などが使われます。 この i は、整数(integer)の頭文字です。

繰返し文の使用例(1)

繰返し文の使用例として、はじめに1+2+...+100の計算を行います。

この問題は、レジの計算をまねることで解決できます。 つまり、それまでの合計を表す変数 sum を用意して、初期値を0とします。 そして、 sum の値を 1増やし、2増やし、…と繰り返し、100増やした時点の sum の値が答になるわけです。 したがって、

        sum += 1; // i = 1
        sum += 2; // i = 2
        ...
        sum += 100; // i = 100

と同じことをfor文で表します。

プログラムは次の通りです。

Summation100.java
/*  1*/ class Summation100 { // 合計100
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, sum = 0;
/*  4*/         for (i = 1; i <= 100; i++) { // 100回繰り返す
/*  5*/             sum += i;
/*  6*/         }
/*  7*/         System.out.println(sum);
/*  8*/     }
/*  9*/ }
コンソール
5050

Completed with exit code: 0

次の例では、1×2×…×10の計算を行います。

合計の計算と同じように考え、変数 product の値を1倍し、2倍し、…と繰り返し、10倍すれば計算できます。 したがって、

        product *= 1; // i = 1
        product *= 2; // i = 2
        ...
        product *= 10; // i = 10

と同じことをfor文で表します。 ただし、 product の初期値は1とします。

プログラムは次の通りです。

Product10.java
/*  1*/ class Product10 { // 積10
/*  2*/     public static void main (String[] args) {
/*  3*/         int i, product = 1;
/*  4*/         for (i = 1; i <= 10; i++) { // 10回繰り返す
/*  5*/             product *= i;
/*  6*/         }
/*  7*/         System.out.println(product);
/*  8*/     }
/*  9*/ }
コンソール
3628800

Completed with exit code: 0

最後の例として、カ氏温度セ氏温度対応表を作ります。

カ氏(華氏、Fahrenheit)温度とは、アメリカで使われる温度で、塩を入れた氷水の温度を0度、人間の体温を96度とするものです。 記号では、°Fと表されます。

セ氏(摂氏、Celsius)温度とは、日本で使われる温度で、水が凍る温度を0度、水が沸騰する温度を100度とするものです。 記号では、°Cと表されます。

カ氏 f 度とセ氏 c 度の変換公式は以下のとおりです。

c =(5/9)×( f −32)
f =(9/5)× c +32

アメリカの天気予報で「明日の気温は80度です。」と言われても、日本の感覚ではピンときません。 そこで、カ氏温度とセ氏温度の対応表を作成し、アメリカの天気予報を理解できるようにします。

プログラムでは、カ氏0.0度からカ氏90.0度まで、10.0度刻みで変換公式に当てはめ、セ氏温度を求めています。 出力では書式を利用し、小数点が揃うようにしています。

FahrenheitCelsiusTable.java
/*  1*/ class FahrenheitCelsiusTable { // カ氏温度セ氏温度対応表
/*  2*/     public static void main (String[] args) {
/*  3*/         int i;
/*  4*/         double fahrenheit, celsius;
/*  5*/         for (i = 0; i < 10; i++) {
/*  6*/             fahrenheit = 10.0 * i; // カ氏10.0度刻み
/*  7*/             celsius = (5.0 / 9.0) * (fahrenheit - 32.0); // 変換公式
/*  8*/             System.out.print("カ氏");
/*  9*/             System.out.printf("%4.1f", fahrenheit); // 全4字、小数点以下1桁
/* 10*/             System.out.print("度はセ氏");
/* 11*/             System.out.printf("%6.2f", celsius); // 全6字、小数点以下2桁
/* 12*/             System.out.println("度です。");
/* 13*/         }
/* 14*/     }
/* 15*/ }
コンソール
カ氏 0.0度はセ氏-17.78度です。
カ氏10.0度はセ氏-12.22度です。
カ氏20.0度はセ氏 -6.67度です。
カ氏30.0度はセ氏 -1.11度です。
カ氏40.0度はセ氏  4.44度です。
カ氏50.0度はセ氏 10.00度です。
カ氏60.0度はセ氏 15.56度です。
カ氏70.0度はセ氏 21.11度です。
カ氏80.0度はセ氏 26.67度です。
カ氏90.0度はセ氏 32.22度です。

Completed with exit code: 0

演習6

長さの単位についは、アメリカではインチ、日本ではセンチが使われます。 1インチは2.54センチです。

プログラムで、0.0インチから9.0インチまで、1.0刻みでセンチに変換し、インチとセンチの対応表を作成してください。

出力では書式を利用し、小数点が揃うようにしてください。

InchCentiTable.java
class InchCentiTable {
    public static void main (String[] args) {



    }
}
コンソール
0.0インチは 0.00センチです。
1.0インチは 2.54センチです。
2.0インチは 5.08センチです。
3.0インチは 7.62センチです。
4.0インチは10.16センチです。
5.0インチは12.70センチです。
6.0インチは15.24センチです。
7.0インチは17.78センチです。
8.0インチは20.32センチです。
9.0インチは22.86センチです。

Completed with exit code: 0

余力のある人は、他の単位についての対応表も作成してください。 出力は10行程度とします。 刻みは、基本的に1.0刻みですが、刻みを変えてもよいです。 出力される数値は、書式を利用して、できるだけ揃うようにしてください。 なお、入力しにくい単位記号は、適宜カタカナなどにしてください。


レポート課題

今日の演習6の答案(Javaプログラム)をメールで提出してください。 差出人は大学発行のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(11月4日)を明記してください。


参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2022年11月4日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2022 Zenjiro Konishi. All rights reserved.