乱数 ( random numbers )とは、規則性のない数の列で、どの数も同じくらい現れるものです。 例えば、さいころを何回も振って出た目を並べると、1から6までの数の列ができますが、それには規則性はなく、それぞれの数も同じくらい現れるので、乱数と言えます。 乱数は、主にゲームで使われますが、シミュレーションや暗号などでも用いられます。
次のプログラムは、0から99までの乱数を生成するものです。 乱数なので、出力結果は下記とは違うのですが、プログラムを実行するたびに、違う数が出力されています。
import java.util.Random; // 乱数のときに書く class RandomTest { // 乱数のときに書く public static void main (String[] args) { // 乱数のときに書く Random rand = new Random(); // 乱数のときに書く int r; r = rand.nextInt(100); // 0から99までの乱数を生成 System.out.println(r); } }
PS ...\Desktop\java1> & ... 'RandomTest' 57 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomTest' 78 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomTest' 66 PS ...\Desktop\java1>
乱数を生成するプログラムでは、1行目から5行目まではそのまま書くものと考えてください。 ただし、3行目はファイル名によって変わります。
7行目で乱数が生成されます。 一般的に、式
rand.nextInt(n)
によって、 n 種類の整数の乱数が生成されます。 このとき、整数は0から始めますので、乱数は0から n -1までとなります。 このプログラムでは、 n =100なので、0から99までの乱数となります。
整数だけでなく、実数の乱数も生成できます。 式
rand.nextDouble()
によって、0.0以上1.0未満の実数の乱数が生成されます。
さて、さいころのように1から6までの数をランダムに生成するには、どうしたらいいでしょうか。 これは、式
rand.nextInt(6) + 1
を計算するとできます。 0から5までの乱数に1を足すと、1から6までの乱数になるのです。
同様に、0.0以上100.0未満の実数の乱数を生成したければ、
rand.nextDouble() * 100.0
とすればよいのです。
import java.util.Random; class RandomTest2 { // 乱数のテスト2 public static void main (String[] args) { Random rand = new Random(); double r; r = rand.nextDouble() * 100.0; // 0.0以上100.0未満の乱数 System.out.println(r); } }
PS ...\Desktop\java1> & ... 'RandomTest2' 56.519319874125614 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomTest2' 7.722231709709925 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomTest2' 2.046519254643775 PS ...\Desktop\java1>
「もし何々が成り立つならば何々する」という条件文では、if文を使いました。 「もし何々が成り立つならば何々する。成り立たないならば何々する。」という条件文では、if-else文を使いました。
「何々が成り立つならば何々する。 そうでなくて、何々が成り立つならば何々する。 どちらも成り立たないならば何々する。 」というような条件文も考えられます。 これは次のように書きます。
if (条件1) { 文1; ... } else if (条件2) { 文2; ... } else { 文3; ... }
「 条件1 」が成り立つならば、「 文1 」、...が実行されます。 「 条件1 」が成り立たなくて、「 条件2 」が成り立つならば、「 文2 」、...が実行されます。 「 条件1 」も「 条件2 」も成り立たないならば、「 文3 」、...が実行されます。
次のプログラムは、入力が正の数ならば「それは正の数です。」と出力し、負の数ならば「それは負の数です。」と出力するものです。 正の数でも負の数でもないならば、0のはずなので、「それは0です。」と出力します。
import java.util.Scanner; class PositiveNegative { // 正の数・負の数 public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); int x; System.out.print("整数を入力してください: "); x = stdIn.nextInt(); if (x > 0) { // 正の数ならば System.out.println("それは正の数です。"); } else if (x < 0) { // そうでなくて負の数ならば System.out.println("それは負の数です。"); } else { // どれでもないならば System.out.println("それは0です。"); } } }
PS ...\Desktop\java1> & ... 'PositiveNegative' 整数を入力してください: 100 それは正の数です。 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'PositiveNegative' 整数を入力してください: -30 それは負の数です。 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'PositiveNegative' 整数を入力してください: 0 それは0です。 PS ...\Desktop\java1>
条件がより多い場合は次のようになります。 「 条件1 」、「 条件2 」、...と順に確かめていき、初めて成り立つのが「 条件i 」ならば、「 文i 」、...が実行されます。 どの条件も成り立たないならば、「 文n+1 」、...が実行されます。
if (条件1) { 文1; ... } else if (条件2) { 文2; ... } ... else if (条件n) { 文n; ... } else { 文n+1; ... }
「もし式の値が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と出力するものです。
import java.util.Scanner; class SwitchTest { // switch文のテスト public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); int x; System.out.print("整数を入力してください: "); x = stdIn.nextInt(); switch (x) { // xの値で場合分け case 3: System.out.println("triangle"); break; // 3の場合 case 4: System.out.println("square"); break; // 4の場合 case 5: System.out.println("pentagon"); break; // 5の場合 default: System.out.println("figure"); break; // どれでもない場合 } } }
PS ...\Desktop\java1> & ... 'SwitchTest' 整数を入力してください: 3 triangle PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'SwitchTest' 整数を入力してください: 4 square PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'SwitchTest' 整数を入力してください: 5 pentagon PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'SwitchTest' 整数を入力してください: 6 figure PS ...\Desktop\java1>
switch文を使わなくても、if-else文を使えば同じことができます。 ただし、プログラムは多少長くなります。 以下のプログラムと比較してください。
import java.util.Scanner; class SwitchTest2 { // switch文のテスト2 public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); int x; System.out.print("整数を入力してください: "); x = stdIn.nextInt(); if (x == 3) { System.out.println("triangle"); } else if (x == 4) { System.out.println("square"); } else if (x == 5) { System.out.println("pentagon"); } else { System.out.println("figure"); } } }
条件文の使用例として、2次方程式、月の最終日、曜日の計算、およびじゃんけんについて考えます。
2次方程式 ax 2 + bx + c =0( a ≠0)の解き方は次の通りです。
これをプログラムにすると、次のようになります。 例えば、2次方程式 x 2 −4 x +3=0の解は、3と1です。
import java.util.Scanner; class QuadraticEquation { // 2次方程式 public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); double a, b, c, d; System.out.print("a = "); a = stdIn.nextDouble(); System.out.print("b = "); b = stdIn.nextDouble(); System.out.print("c = "); c = stdIn.nextDouble(); d = b * b - 4.0 * a * c; // 判別式 if (Math.abs(d) < 1.0E-10) { // 0.0とほとんど等しい System.out.println(-b / (2.0 * a)); } else if (d > 0.0) { System.out.println((-b + Math.sqrt(d)) / (2.0 * a)); System.out.println((-b - Math.sqrt(d)) / (2.0 * a)); } else { // (d < 0.0) System.out.println("実数解はありません。"); } } }
PS ...\Desktop\java1> & ... 'QuadraticEquation' a = 1.0 b = -4.0 c = 3.0 3.0 1.0 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'QuadraticEquation' a = 1.0 b = -4.0 c = 4.0 2.0 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'QuadraticEquation' a = 1.0 b = -4.0 c = 5.0 実数解はありません。 PS ...\Desktop\java1>
月の最終日は、小の月(2月、4月、6月、9月、11月)ならば30日、大の月(それ以外)ならば31日です。 ただし、2月は例外で、うるう年ならば29日、そうでないならば28日です。 うるう年の判定は、前回の授業で説明しました。
import java.util.Scanner; class LastDayOfMonth { // 月の最終日 public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); int year, month, lastDay; System.out.print("年を入力してください: "); year = stdIn.nextInt(); System.out.print("月を入力してください: "); month = stdIn.nextInt(); if (month == 2) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { lastDay = 29; // うるう年の2月 } else { lastDay = 28; // うるう年でない2月 } } else if (month == 4 || month == 6 || month == 9 || month == 11) { lastDay = 30; // 2月以外の小の月 } else { lastDay = 31; // 大の月 } System.out.println(lastDay); } }
PS ...\Desktop\java1> & ... 'LastDayOfMonth' 年を入力してください: 2024 月を入力してください: 2 29 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'LastDayOfMonth' 年を入力してください: 2025 月を入力してください: 2 28 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'LastDayOfMonth' 年を入力してください: 2025 月を入力してください: 4 30 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'LastDayOfMonth' 年を入力してください: 2025 月を入力してください: 5 31 PS ...\Desktop\java1>
曜日の計算は、ツェラー(Zeller)の公式という有名な公式で計算します。 これは、西暦 y 年 m 月 d 日ならば、式
を計算し、 h が0ならば日曜日、1ならば月曜日、2ならば火曜日、3ならば水曜日、4ならば木曜日、5ならば金曜日、6ならば土曜日とするものです。 ここで、[…]は床関数(正なら小数切り捨て)、modは剰余演算(割った余り)です。 ただし、1月と2月については、前年の13月と14月と考えます。
import java.util.Scanner; class DayOfWeek { // 曜日の計算 public static void main (String[] args) { Scanner stdIn = new Scanner(System.in); int year, month, day, y, m, h; System.out.print("西暦を入力してください: "); year = stdIn.nextInt(); System.out.print("月を入力してください: "); month = stdIn.nextInt(); System.out.print("日を入力してください: "); day = stdIn.nextInt(); if (month == 1 || month == 2) { // 1月と2月は y = year - 1; // 前年の m = month + 12; // 13月と14月とする } else { y = year; m = month; } // ツェラーの公式 h = (y + y / 4 - y / 100 + y / 400 + (13 * m + 8) / 5 + day) % 7; switch (h) { case 0: System.out.println("日曜日"); break; case 1: System.out.println("月曜日"); break; case 2: System.out.println("火曜日"); break; case 3: System.out.println("水曜日"); break; case 4: System.out.println("木曜日"); break; case 5: System.out.println("金曜日"); break; case 6: System.out.println("土曜日"); break; default: System.out.println("エラー"); break; } } }
PS ...\Desktop\java1> & ... 'DayOfWeek' 西暦を入力してください: 2025 月を入力してください: 5 日を入力してください: 9 金曜日 PS ...\Desktop\java1>
じゃんけんプログラムでは、同じ確率でランダムに「グー」、「チョキ」、「パー」を出すことにします。 0から2までの乱数を生成し、0ならば「グー」を、1ならば「チョキ」を、2ならば「パー」を、それぞれ出力します。
import java.util.Random; class RandomJanken { // ランダムなじゃんけん public static void main (String[] args) { Random rand = new Random(); int r; r = rand.nextInt(3); // 0から2までの乱数 switch (r) { case 0: System.out.println("グー"); break; case 1: System.out.println("チョキ"); break; case 2: System.out.println("パー"); break; default: System.out.println("エラー"); break; } } }
PS ...\Desktop\java1> & ... 'RandomJanken' パー PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomJanken' パー PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomJanken' チョキ PS ...\Desktop\java1>
おみくじプログラムを作成してください。 「大吉」、「吉」、「中吉」、「小吉」、「凶」の5種類の運勢が、同じ確率でランダムに出力されるようにしてください。
import java.util.Random; class RandomOmikuji { public static void main (String[] args) { Random rand = new Random(); } }
PS ...\Desktop\java1> & ... 'RandomOmikuji' 大吉 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomOmikuji' 大吉 PS ...\Desktop\java1>
PS ...\Desktop\java1> & ... 'RandomOmikuji' 吉 PS ...\Desktop\java1>
余力のある人は、運勢の種類(個数と語句)を変えたものも作成してください。
今日の演習5の答案(Javaプログラム)をメールで提出してください。 差出人は大学発行のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(5月9日)を明記してください。