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

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

目次
索引

乱数

乱数とは

乱数 random numbers )とは、規則性のない数の列で、どの数も同じくらい現れるものです。 例えば、さいころを何回も振って出た目を並べると、1から6までの数の列ができますが、それには規則性はなく、それぞれの数も同じくらい現れるので、乱数と言えます。 乱数は、主にゲームで使われますが、シミュレーションや暗号などでも用いられます。

Javaでは、式

Math.random()

で乱数が発生します。 発生する数は、0.0以上1.0未満の実数で、毎回異なります。

次のプログラムでは、乱数を1つ発生させています。 乱数なので、出力結果は下記とは違うでしょう。

/*  1*/ class RandomTest { // 乱数のテスト
/*  2*/     public static void main (String[] args) {
/*  3*/         double random;
/*  4*/         random = Math.random(); // 乱数を発生
/*  5*/         System.out.println(random);
/*  6*/     }
/*  7*/ }
Z:\Desktop\java1>java RandomTest
0.16865863188578234

Z:\Desktop\java1>java RandomTest
0.8440982279637195

Z:\Desktop\java1>java RandomTest
0.10163212550412803

Z:\Desktop\java1>

乱数の使用例

例として、さいころのように1から6までの数をランダムに発生させることを考えます。 これは、次のように計算するとできます。

  1. 0.0以上1.0未満の乱数を発生させる。
  2. それを6倍すると、0.0以上6.0未満の乱数となる。
  3. それを整数に変換すると、0から5までの乱数となる。
  4. それに1を足すと、1から6までの乱数となる。

次のプログラムでは、1から6までの乱数を1つ発生させています。

/*  1*/ class RandomTest2 { // 乱数のテスト2
/*  2*/     public static void main (String[] args) {
/*  3*/         int random;
/*  4*/         random = ((int) (Math.random() * 6)) + 1; // 1から6までの乱数
/*  5*/         System.out.println(random);
/*  6*/     }
/*  7*/ }
Z:\Desktop\java1>java RandomTest2
5

Z:\Desktop\java1>java RandomTest2
5

Z:\Desktop\java1>java RandomTest2
4

Z:\Desktop\java1>

条件文(3)

if-else文(2)

「もし何々が成り立つならば何々する」という条件文では、if文を使いました。 「もし何々が成り立つならば何々する。成り立たないならば何々する。」という条件文では、if-else文を使いました。

「何々が成り立つならば何々する。 そうでなくて、何々が成り立つならば何々する。 どちらも成り立たないならば何々する。 」というような条件文も考えられます。 これは次のように書きます。

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

条件1 」が成り立つならば、「 文1 」、...が実行されます。 「 条件1 」が成り立たなくて、「 条件2 」が成り立つならば、「 文2 」、...が実行されます。 「 条件1 」も「 条件2 」も成り立たないならば、「 文3 」、...が実行されます。

多重if-else文の流れ
多重if-else文の流れ(true=成り立つ、false=成り立たない)

次のプログラムは、入力が正の数ならば「それは正の数です。」と出力し、負の数ならば「それは負の数です。」と出力するものです。 正の数でも負の数でもないならば、0のはずなので、「それは0です。」と出力します。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class PositiveNegative { // 正の数・負の数
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int x;
/*  8*/         System.out.print("整数を入力してください: ");
/*  9*/         x = Integer.parseInt(br.readLine());
/* 10*/         if (x > 0) { // 正の数ならば
/* 11*/             System.out.println("それは正の数です。");
/* 12*/         } else if (x < 0) { // そうでなくて負の数ならば
/* 13*/             System.out.println("それは負の数です。");
/* 14*/         } else { // どれでもないならば
/* 15*/             System.out.println("それは0です。");
/* 16*/         }
/* 17*/     }
/* 18*/ }
Z:\Desktop\java1>java PositiveNegative
整数を入力してください: 100
それは正の数です。

Z:\Desktop\java1>java PositiveNegative
整数を入力してください: -30
それは負の数です。

Z:\Desktop\java1>java PositiveNegative
整数を入力してください: 0
それは0です。

Z:\Desktop\java1>

条件がより多い場合は次のようになります。 「 条件1 」、「 条件2 」、...と順に確かめていき、初めて成り立つのが「 条件i 」ならば、「 文i 」、...が実行されます。 どの条件も成り立たないならば、「 文n+1 」、...が実行されます。

if (条件1) {
    文1; ...
} else if (条件2) {
    文2; ...
}
...
  else if (条件n) {
    文n; ...
} else {
    文n+1; ...
}

switch文

「もし式の値が1ならば何々する。2ならば何々する。…」という条件文は、条件が「式の値が何ならば」という特別なパターンですが、それなりに使われます。 Javaでは、そのような条件文のために、switch文が用意されています。

switch文 は、 case文 を伴い、次のように書きます。

switch () {
    case 定数1: 文1; ... break;
    case 定数2: 文2; ... break;
    ...
    case 定数n: 文n; ... break;
    default: 文n+1; ... break;
}

これで、「 」の値が「 定数1 」ならば「 文1 」、...が実行されます。 「 定数2 」ならば「 文2 」、...が実行されます。 以下同様ですが、どれでもないならば「 文n+1 」、...が実行されます。

case文の定数は整数に限ります。 また、case文の定数は、1つのswitch文の中ではすべて異なるようにします。 case文の並びの最後には、どれでもない場合を表す default を書きます。 それぞれのcase文の最後には、 break を書きます。

次のプログラムは、入力された数が3ならばtriangleと出力し、4ならばsquareと出力し、5ならばpentagonと出力し、それ以外ならばfigureと出力するものです。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class SwitchTest { // switch文のテスト
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int x;
/*  8*/         System.out.print("整数を入力してください: ");
/*  9*/         x = Integer.parseInt(br.readLine());
/* 10*/         switch (x) { // xの値で場合分け
/* 11*/             case 3: System.out.println("triangle"); break; // 3の場合
/* 12*/             case 4: System.out.println("square"); break; // 4の場合
/* 13*/             case 5: System.out.println("pentagon"); break; // 5の場合
/* 14*/             default: System.out.println("figure"); break; // どれでもない場合
/* 15*/         }
/* 16*/     }
/* 17*/ }
Z:\Desktop\java1>java SwitchTest
整数を入力してください: 3
triangle

Z:\Desktop\java1>java SwitchTest
整数を入力してください: 4
square

Z:\Desktop\java1>java SwitchTest
整数を入力してください: 5
pentagon

Z:\Desktop\java1>java SwitchTest
整数を入力してください: 6
figure

Z:\Desktop\java1>

switch文を使わなくても、if-else文を使えば同じことができます。 ただし、プログラムは多少長くなります。 以下のプログラムと比較してください。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class SwitchTest2 { // switch文のテスト2
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int x;
/*  8*/         System.out.print("整数を入力してください: ");
/*  9*/         x = Integer.parseInt(br.readLine());
/* 10*/         if (x == 3) {
/* 11*/             System.out.println("triangle");
/* 12*/         } else if (x == 4) {
/* 13*/             System.out.println("square");
/* 14*/         } else if (x == 5) {
/* 15*/             System.out.println("pentagon");
/* 16*/         } else {
/* 17*/             System.out.println("figure");
/* 18*/         }
/* 19*/     }
/* 20*/ }

条件文の使用例(2)

条件文の使用例として、2次方程式、月の最終日、曜日の計算、およびじゃんけんについて考えます。

2次方程式 ax 2 bx c =0( a ≠0)の解き方は次の通りです。

  1. 判別式 D b 2 −4 ac を計算する。
  2. D =0ならば、解は1つ:
    2次方程式の解
  3. D >0ならば、解は2つ:
    2次方程式の解
  4. D <0ならば、(実数)解はない。

これをプログラムにすると、次のようになります。 例えば、2次方程式 x 2 −4 x +3=0の解は、3と1です。

/*  1*/ import java.io.*;
/*  2*/ 
/*  3*/ class QuadraticEquation { // 2次方程式
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         double a, b, c, d;
/*  8*/         System.out.print("a = ");
/*  9*/         a = Double.parseDouble(br.readLine());
/* 10*/         System.out.print("b = ");
/* 11*/         b = Double.parseDouble(br.readLine());
/* 12*/         System.out.print("c = ");
/* 13*/         c = Double.parseDouble(br.readLine());
/* 14*/         d = b * b - 4.0 * a * c; // 判別式
/* 15*/         if (Math.abs(d) < 1.0E-10) { // 0.0とほとんど等しい
/* 16*/             System.out.println(-b / (2.0 * a));
/* 17*/         } else if (d > 0.0) {
/* 18*/             System.out.println((-b + Math.sqrt(d)) / (2.0 * a));
/* 19*/             System.out.println((-b - Math.sqrt(d)) / (2.0 * a));
/* 20*/         } else { // (d < 0.0)
/* 21*/             System.out.println("実数解はありません。");
/* 22*/         }
/* 23*/     }
/* 24*/ }
Z:\Desktop\java1>java QuadraticEquation
a = 1.0
b = -4.0
c = 3.0
3.0
1.0

Z:\Desktop\java1>java QuadraticEquation
a = 1.0
b = -4.0
c = 4.0
2.0

Z:\Desktop\java1>java QuadraticEquation
a = 1.0
b = -4.0
c = 5.0
実数解はありません。

Z:\Desktop\java1>

月の最終日は、小の月(2月、4月、6月、9月、11月)ならば30日、大の月(それ以外)ならば31日です。 ただし、2月は例外で、うるう年ならば29日、そうでないならば28日です。 うるう年の判定は、前回の授業で説明しました。

/*  1*/ import java.io.*;
/*  2*/ 
/*  3*/ class LastDayOfMonth { // 月の最終日
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int year, month, lastDay;
/*  8*/         System.out.print("年を入力してください: ");
/*  9*/         year = Integer.parseInt(br.readLine());
/* 10*/         System.out.print("月を入力してください: ");
/* 11*/         month = Integer.parseInt(br.readLine());
/* 12*/         if (month == 2) {
/* 13*/             if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
/* 14*/                 lastDay = 29; // うるう年の2月
/* 15*/             } else {
/* 16*/                 lastDay = 28; // うるう年でない2月
/* 17*/             }
/* 18*/         } else if (month == 4 || month == 6 || month == 9 || month == 11) {
/* 19*/             lastDay = 30; // 2月以外の小の月
/* 20*/         } else {
/* 21*/             lastDay = 31; // 大の月
/* 22*/         }
/* 23*/         System.out.println(lastDay);
/* 24*/     }
/* 25*/ }
Z:\Desktop\java1>java LastDayOfMonth
年を入力してください: 2016
月を入力してください: 2
29

Z:\Desktop\java1>java LastDayOfMonth
年を入力してください: 2019
月を入力してください: 2
28

Z:\Desktop\java1>java LastDayOfMonth
年を入力してください: 2019
月を入力してください: 9
30

Z:\Desktop\java1>java LastDayOfMonth
年を入力してください: 2019
月を入力してください: 10
31

Z:\Desktop\java1>

曜日の計算は、ツェラー(Zeller)の公式という有名な公式で計算します。 これは、西暦 y m d 日ならば、式

ツェラーの公式

を計算し、 h が0ならば日曜日、1ならば月曜日、2ならば火曜日、3ならば水曜日、4ならば木曜日、5ならば金曜日、6ならば土曜日とするものです。 ここで、[…]は床関数(正なら小数切り捨て)、modは剰余演算(割った余り)です。 ただし、1月と2月については、前年の13月と14月と考えます。

/*  1*/ import java.io.*;
/*  2*/
/*  3*/ class DayOfWeek { // 曜日の計算
/*  4*/     public static void main (String[] args) throws IOException {
/*  5*/         InputStreamReader isr = new InputStreamReader(System.in);
/*  6*/         BufferedReader br = new BufferedReader(isr);
/*  7*/         int year, month, day, y, m, h;
/*  8*/         System.out.print("西暦を入力してください: ");
/*  9*/         year = Integer.parseInt(br.readLine());
/* 10*/         System.out.print("月を入力してください: ");
/* 11*/         month = Integer.parseInt(br.readLine());
/* 12*/         System.out.print("日を入力してください: ");
/* 13*/         day = Integer.parseInt(br.readLine());
/* 14*/         if (month == 1 || month == 2) { // 1月と2月は
/* 15*/             y = year - 1; // 前年の
/* 16*/             m = month + 12; // 13月と14月とする
/* 17*/         } else {
/* 18*/             y = year;
/* 19*/             m = month;
/* 20*/         }
/* 21*/         // ツェラーの公式
/* 22*/         h = (y + y / 4 - y / 100 + y / 400 + (13 * m + 8) / 5 + day) % 7;
/* 23*/         switch (h) {
/* 24*/             case 0: System.out.println("日曜日"); break;
/* 25*/             case 1: System.out.println("月曜日"); break;
/* 26*/             case 2: System.out.println("火曜日"); break;
/* 27*/             case 3: System.out.println("水曜日"); break;
/* 28*/             case 4: System.out.println("木曜日"); break;
/* 29*/             case 5: System.out.println("金曜日"); break;
/* 30*/             case 6: System.out.println("土曜日"); break;
/* 31*/             default: System.out.println("エラー"); break;
/* 32*/         }
/* 33*/     }
/* 34*/ }
Z:\Desktop\java1>java DayOfWeek
西暦を入力してください: 2019
月を入力してください: 11
日を入力してください: 1
金曜日

Z:\Desktop\java1>

じゃんけんプログラムでは、同じ確率でランダムに「グー」、「チョキ」、「パー」を出すことにします。 0から2までの乱数を発生させ、0ならば「グー」を、1ならば「チョキ」を、2ならば「パー」を、それぞれ出力します。

/*  1*/ class RandomJanken { // ランダムなじゃんけん
/*  2*/     public static void main (String[] args) {
/*  3*/         int random;
/*  4*/         random = (int) (Math.random() * 3); // 0から2までの乱数
/*  5*/         switch (random) {
/*  6*/             case 0: System.out.println("グー"); break;
/*  7*/             case 1: System.out.println("チョキ"); break;
/*  8*/             case 2: System.out.println("パー"); break;
/*  9*/             default: System.out.println("エラー"); break;
/* 10*/         }
/* 11*/     }
/* 12*/ }
Z:\Desktop\java1>java RandomJanken
パー

Z:\Desktop\java1>java RandomJanken
パー

Z:\Desktop\java1>java RandomJanken
チョキ

Z:\Desktop\java1>

演習6

おみくじプログラムを作成してください。 「大吉」、「吉」、「中吉」、「小吉」、「凶」の5種類の運勢が、同じ確率でランダムに出力されるようにしてください。

Z:\Desktop\java1>java RandomOmikuji
大吉

Z:\Desktop\java1>java RandomOmikuji
大吉

Z:\Desktop\java1>java RandomOmikuji
吉

Z:\Desktop\java1>

余力のある人は、運勢の種類(個数と語句)を変えたものも作成してください。


レポート課題

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


参考文献


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

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