[目次] [前回] [次回] [重要語索引]

第4週: いろいろなデータ

4. 1 
4. 2 小数の計算
4. 3 浮動小数点数
4. 4 練習問題
4. 5 浮動小数点数の計算における注意点
4. 6 練習問題
4. 7 真偽値型
4. 8 条件の組み合わせ(1)
4. 9 練習問題
4.10 条件の組み合わせ(2)
4.11 練習問題
4.12 条件の組み合わせ(3)
4.13 宿題
4.14 おまけ1
4.15 おまけ2

4.1 型

変数は、それぞれ記憶できるデータの種類が決まっています。宣言する時にint と書いてある変数は整数しか記憶できず、String と書いてある変数は文字列しか記憶できません。このようなデータの種類のことを(type)と呼びます。

一見同じように見えるデータでも、型が違うと全く違う取り扱いを受けます。例えば、

    1 + 2
は整数の加算なので、結果は 3 になりますが、
    "1" + "2"
は文字列の結合なので、結果は "12" になります。

4.2 小数の計算

第1週の宿題で、円をドルに直すプログラムForeignExchange.java を作りましたが、計算が整数で行われるため、1ドル未満が切り捨てとなり、106円も200円も1ドルと表示されてしまいます。これを小数部分まで計算するように直すと、次のようになります。
43
44
45
46
47
48
49
    void sfcProcess () {
	//ここに自分のプログラムを書く
        double dollar, yen; // 倍精度浮動小数点数型変数の宣言
        yen = Double.parseDouble(sfcInput()); // 倍精度浮動小数点数型に変換
        dollar = yen / 106; // 浮動小数点数の除算
        sfcOutput(String.valueOf(dollar)); // 文字列に変換
    }

4.3 浮動小数点数

コンピュータのメモリは有限ですから、浮動小数点数は数学的な実数とは異なり、有限の桁数しか表現できません。例えば、1/3は数学的には 0.333333… ですが、浮動小数点数では 0.3333333 のように、あるところ以下は丸めて(切捨て、四捨五入など)しまいます。

4.4 練習問題

上のプログラムでは、1セント未満のところまで表示されてしまいます。1セント未満を切り捨てて、小数部分を2桁にするように書き換えなさい。

4.5 浮動小数点数の計算における注意点

4.6 練習問題

1/1000000 +…+ 1/3 + 1/2 + 1/1 を計算するプログラムを書いてみましょう。結果は文字で表示しますから、SfcTemplate1.java,SfcTemplate1.htmlFloating.java, Floating.html にコピーします。
43
44
45
46
47
48
49
50
    void sfcProcess () {
	//ここに自分のプログラムを書く
	double x = 0.0;  // 合計を覚えておく変数
	for (int i = 1000000; i >= 1; i = i - 1) {  // 1000000 から 1 まで
	    x = x + 1.0 / i; // 合計に 1.0 / i を加える
	}
	sfcOutput(String.valueOf(x));
    }
これを 1/1 + 1/2 + 1/3 +…+ 1/1000000 と逆順に足すように変更し、実行結果を比べてみなさい。なぜ、このようになるのでしょうか。

4.7 真偽値型

boolean 型は、条件が成り立つかどうかを表す型です。この型の値は truefalse の二つしかありません。

4.8 条件の組み合わせ(1)

ある年が閏年かどうかを表示するプログラムを書いてみましょう。閏年かどうかは次の規則で決まっています。

  1. 西暦年が4で割り切れる年が閏年です。
  2. ただし、100で割り切れる年は閏年ではありません。
  3. ただし、400で割り切れる年はやっぱり閏年です。

4で割り切れるということは、4で割った余りが 0 ということです。割り算の余りを求める演算は % ですから、条件1だけを考える if 文は次のようになります。

       if ( year % 4 == 0 ) {  // 4で割り切れる時
           sfcOutput("Leap year");
       } else {                // 4で割り切れない時
           sfcOutput("Ordinary year");
       }
ただし、整数変数 year に西暦年を代入してあるとします。

条件2は、条件1が成り立つ場合に、さらにテストしなければいけないわけですから、上の if 文の4で割り切れる場合のブロックに、さらにif 文を書きます。

       if ( year % 4 == 0 ) {  // 4で割り切れる時
           if ( year % 100 == 0 ) {  // 100で割り切れる時
               sfcOutput("Ordinary year");
	   } else {                  // 100で割り切れない時
               sfcOutput("Leap year");
	   }
       } else {                // 4で割り切れない時
           sfcOutput("Ordinary year");
       }

4.9 練習問題

  1. SfcTemplate1.java, SfcTemplate1.html を LeapYear.java,LeapYear.htmlにコピーし、上の if 文を使って、西暦年を入力すると閏年かどうかを出力するプログラムを書きなさい。
  2. 上の if 文は条件3を考慮していないので、誤った結果が出る場合があります。条件3も正しく判定するように書き換えなさい。正しいプログラムならば
    InputOutput
    1996Leap year
    1900Ordinary year
    2000Leap year
    となるはずです。

4.10 条件の組み合わせ(2)

上の if 文は、条件とブロックの対応が分かりにくいので、見やすくなるように書き換えてみましょう。まず、条件を逆にして、成り立つ場合と成り立たない場合を入れ替えます。

       if ( year % 4 != 0 ) { // 4で割り切れない時
           sfcOutput("Ordinary year");
       } else {               // 4で割り切れる時
           if ( year % 100 != 0 ) {  // 100で割り切れない時
               sfcOutput("Leap year");
	   } else {                  // 100で割り切れる時
               sfcOutput("Ordinary year");
	   }
       }
ブロックは、複数の文をまとめて一つの文にするものです。ブロックに含まれる文が一つだけなら、その文を直接書くのと同じなので、{ } が省略できます。上の、4で割り切れない場合の if 文を、直接 else の後に書くと、次のようになります。
       if ( year % 4 != 0 ) { // 4で割り切れない時
           sfcOutput("Ordinary year");
       } else                 // 4で割り切れる時
           if ( year % 100 != 0 ) {  // 100で割り切れない時
               sfcOutput("Leap year");
	   } else {                  // 100で割り切れる時
               sfcOutput("Ordinary year");
	   }
このように、else の後に直接 if が来る場合は、続けて書くのが普通です。
       if ( year % 4 != 0 ) {
           sfcOutput("Ordinary year");
       } else if ( year % 100 != 0 ) {
           sfcOutput("Leap year");
       } else {
           sfcOutput("Ordinary year");
       }
一般に、複数の条件を次々とテストして、それに応じた処理をするには、次のように書くと、条件と処理の対応が分かりやすくなります。
       if ( 条件1 ) {
           条件1が成り立つ場合のブロック
       } else if ( 条件2 ) {
           条件2が成り立つ場合のブロック
       } else if ( 条件3 ) {
           ........
           ........
       } else {
           それ以外の場合のブロック
       }

条件が成り立つ場合のブロックの代わりに直接 if 文を書くと、ifelse の対応が分かりにくくなるので注意しましょう。

        if (条件1) if (条件2) 文1 else 文2
は、
        if (条件1) { if (条件2) 文1 } else 文2
ではなく、
        if (条件1) { if (条件2) 文1 else 文2 }
という意味になると決められています。

4.11 練習問題

前の練習問題のプログラムを、else の後に直接 if が来る書き方に変更しなさい。
  1. 条件が成り立つ場合のブロックに if 文が入っていれば、条件を逆にして else の後に if 文が来るようにします。最初からそういう形になっていれば、条件を逆にする必要はありません。
  2. else の後の { } を省略します。ブロックの中に文が2つ以上あると、省略できません。
  3. 改行や左端の空白を整えて見やすくします。

4.12 条件の組み合わせ(3)

if 文の組み合わせは、複数の条件を組み合わせた条件式を使って、一つのif 文で書くこともできます。組み合わせるための演算(boolean 型の値から boolean 型の値を計算する)には次の種類があります。
!否定
&かつ
&&かつ
|または
||または
&&&||| はほぼ同じ意味ですが、普通は &&|| を使います。

&&&||| の違いは何でしょうか?&| は両側の式を必ず計算しますが、&&|| は左側の式を計算して結果が分かってしまった場合は、右側の式を計算しません。実行速度は速くなりますが、右側の式を必ず実行してほしいとき(変数への代入など、後に影響をおよぼすものを含んでいる場合)には使えません。

前に書いた if 文は次のように書くこともできます。

       if ( year % 4 == 0 && year % 100 != 0 ) {
           sfcOutput("Leap year");
       } else {
           sfcOutput("Ordinary year");
       }

4.13 宿題

前の練習問題のプログラムを、if 文を一つだけ使うように変更しなさい。

4.14 おまけ1

三角関数、平方根などを計算するメソッドが用意されています。詳しくはこちらを見てください。

次のプログラムはサインのグラフを描くものです。
45
46
47
48
49
50
51
    void sfcDraw(Graphics g) {
	//ここに自分のプログラムを書く
	for (int t = -180; t <= 180; t = t + 10) {
	    int x = (t + 180) * 300 / 360;
	    g.drawLine(x, 150, x, 150-(int)(Math.sin(Math.toRadians(t))*150));
	}
    }

次のような図形を描いてみましょう。

sin and cos

4.15 おまけ2

X座標とY座標を周期の違う三角関数で指定すると、リサージュ図形と呼ばれる図形が描けます。次のようなリサージュ図形を描くプログラムを書きなさい。(正確に同じ図形でなくてもかまいません)

lissajous


[目次] [前回] [次回] [重要語索引]

慶應義塾大学の授業以外での無断利用、複製はご遠慮下さい。
Copyright (c) 2000 慶應義塾大学