M.Hiroi's Home Page

お気楽 Java プログラミング入門

Java の基礎知識 (2)

[ PrevPage | Java | NextPage ]

はじめに

前回は Java の基本として、数と文字列、if 文と while 文について説明しました。今回は配列と for 文、switch 文について説明します。

●配列

Java の配列 (array) はデータを一列に並べたもので、C/C++の 1 次元配列と同等のデータ構造です。配列に格納されたデータを要素といいます。配列はホテルやマンションの部屋にたとえるとわかりやすいと思います。ホテル全体を配列とすると、各部屋がデータを格納する変数と考えることができます。ホテルでは、ルームナンバーによって部屋を指定しますね。配列の場合も、整数値によってデータを格納する変数を指定することができます。この整数値を「添字 (subscripts)」といいます。


                  図 1 : 配列の構造

たとえば、10 個のデータを格納する配列を考えてみます。これは、平屋建てのホテルで、部屋が 10 室あると考えてください。この場合は上図に示すように、データを格納する変数が並んでいて、それぞれ 0 から 9 までの添字で指定することができます。Java の場合、C/C++と同じく、添字は 0 から順番に数えます。

Java の場合、配列は次のように宣言します。

  1. データ型[] 変数名 = new データ型 [大きさ];
  2. データ型 変数名 [] = new データ型 [大きさ];
  3. データ型[] 変数名 = {値1, ..., 値N};
  4. データ型 変数名 [] = {値1, ..., 値N};

1 と 2 の場合、データ型は配列に格納する要素のデータ型を指定します。その後ろの [ ] は配列の宣言であることを表します。それから変数名を指定します。変数名の後ろに [ ] を付けてもかまいません。配列の実体は new データ型 [大きさ] で指定します。また、次のように var を使って配列を宣言することもできます。

var 変数名 = new データ型 [大きさ];

var を使うとデータ型の指定が左辺だけで済むので簡単です。

一般に、スクリプト言語の多くは配列の大きさを自由に変えることができる「可変長配列」をサポートしています。ところが、Java の配列はC/C++と同様にあとから大きさを変更することはできません。そのかわり、Java には可変長配列を実装したクラス ArrayList がパッケージ java.util に用意されています。

要素の初期値はデータ型によって決まります。数値の場合は 0 に、boolean の場合は false に初期化されます。初期値を設定したい場合は、3 と 4 のように {値1, ..., 値N} で要素の値を設定します。この場合、{ } の中の要素数が配列の大きさになります。このとき、データ型と値のデータ型が一致しないとコンパイルエラーになります。

なお、var で配列を宣言する場合、左辺式にデータ型が指定されていないとエラーになります。次のように、{...} の前にデータ型を指定してください。

var 変数名 = new データ型[] {値1, ..., 値N};

簡単な例を示しましょう。

jshell> var a = new int [4]
a ==> int[4] { 0, 0, 0, 0 }

jshell> var b = new int[] {1,2,3,4,5,6,7,8}
b ==> int[8] { 1, 2, 3, 4, 5, 6, 7, 8 }

jshell> a.length
$3 ==> 4

jshell> b.length
$4 ==> 8

jshell> a[0]
$5 ==> 0

jshell> b[0]
$6 ==> 1

jshell> a[0] = 10
$7 ==> 10

jshell> b[0] = 20
$8 ==> 20

jshell> a
a ==> int[4] { 10, 0, 0, 0 }

jshell> b
b ==> int[8] { 20, 2, 3, 4, 5, 6, 7, 8 }

配列の要素は角カッコ [ ] を使ってアクセスします。これはC/C++と同じです。配列の要素を取り出して変数に代入することも、配列の要素を書き換えることもできます。配列は自分自身の大きさを知っていて、変数名 + ドット ( . ) + length で値を取り出すことができます。

配列は入れ子にすることができます。つまり、配列の要素に配列を入れてもかまいません。これで多次元配列を表すことができます。簡単な例を示しましょう。

jshell> var c = new int [3][3]
c ==> int[3][] { int[3] { 0, 0, 0 }, int[3] { 0, 0, 0 }, int[3] { 0, 0, 0 } }

jshell> var d = new int[][] {{1,2,3},{4,5,6},{7,8,9}}
d ==> int[3][] { int[3] { 1, 2, 3 }, int[3] { 4, 5, 6 }, int[3] { 7, 8, 9 } }

jshell> c.length
$13 ==> 3

jshell> d.length
$14 ==> 3

jshell> c[0][0]
$15 ==> 0

jshell> d[2][2]
$16 ==> 9

jshell> c[0][0] = 10
$17 ==> 10

jshell> d[2][2] = 20
$18 ==> 20

jshell> c
c ==> int[3][] { int[3] { 10, 0, 0 }, int[3] { 0, 0, 0 }, int[3] { 0, 0, 0 } }

jshell> d
d ==> int[3][] { int[3] { 1, 2, 3 }, int[3] { 4, 5, 6 }, int[3] { 7, 8, 20 } }

多次元配列は [ ] を複数つけることで宣言します。2 次元配列の場合、int [ ][ ] のように [ ] を 2 つ付けます。たとえば、new int [3][3] のように指定すると、配列 c の大きさは 3 で、その要素は大きさ 3 の配列になります。また、初期値を指定する場合は、{ } の中で {1, 2, 3} のように初期値付きで要素を指定します。これで 2 次元配列を初期化することができます。

要素のアクセスは簡単で、最初の [ ] で配列に格納されている配列を取り出し、次の [ ] で取り出した配列の要素を指定します。たとえば、d[2][2] は d[2] に格納されている配列 {7, 8, 9} を取り出し、次の [2] でその配列の 2 番目の要素を指定します。したがって、d[2][2] の値は 9 になります。d[2][2] = 20 とすると 9 が書き換えられて 20 になります。

●for 文による繰り返し

配列を操作するときに、とても役に立つ繰り返し文を紹介しましょう。まず、C/C++でもお馴染みの for 文です。Java の for 文はC/C++とほぼ同じです。

for (初期化; 条件部; 更新処理) { 処理A; ...; 処理Z; }

          図 2 : for 文の処理

for 文の特徴は、いちばん最初に行われる初期化と、繰り返すたびに行われる更新処理があることです。上図を見ればおわかりのように、初期化はただ一度しか行われず、更新処理はブロックの処理を実行してから行われます。なお、繰り返す処理が一つしかない場合は { } を省略することができます。また、初期化で変数を宣言する場合、var を使ってもかまいません。

簡単な使用例を示しましょう。

jshell> for (int i = 0; i < 10; i++) System.out.println("Hello, World!")
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

jshell> for (var i = 0; i < 10; i++) System.out.println("Hello, World!")
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

まず、int i = 0; で変数 i を 0 に初期化します。この処理は for 文が始まるときに一度だけ実行されます。次に条件部 i < 10 がチェックされます。i は 0 ですから条件を満たしますね。そこで、ブロックの処理が行われ、println() により Hello, World! が表示されます。初期化は int i = 0; のかわりに var i = 0; としても大丈夫です。

次に、更新処理 i++ が行われます。変数 i の値を +1 したら、条件部のチェックを行います。あとは、while と同様に条件部が成立しているあいだは、ブロックの処理と更新処理を繰り返します。結局、i の値は 10 になるので、条件部が不成立となり繰り返しを終了します。したがって、このプログラムを実行すると Hello, World! が 10 回表示されます。

●拡張 for 文

Java は JDK 5 から拡張 for 文を使用することができます。拡張 for 文は配列から順番に要素を取り出して変数に代入し、ブロックに書かれている処理を繰り返し実行します。拡張 for 文は Perl の foreach や Python, Ruby の for 文と同じです。拡張 for 文の構文と動作を下図に示します。

for (データ型 変数名: コレクション) { 処理A; ...; 処理Z; }

      図 3 : 拡張 for 文の処理

for 文と同様に、変数は var を使って宣言してもかまいません。

一般に、複数の要素を格納するデータ型を「コレクション (collection)」とか「コンテナ (container)」と呼びます。Java のライブラリには ArayList など便利なコレクションが用意されていて、それらにも拡張 for 文を適用することができます。なお、変数のデータ型とコレクションに格納されているデータ型が一致しないとコンパイルでエラーとなります。

たとえば、拡張 for 文と通常の for 文で、配列の要素の合計を求めると次のようになります。

jshell> var a = new int[] {1,2,3,4,5,6,7,8,9,10}
a ==> int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

jshell> int sum = 0
sum ==> 0

jshell> for (int n: a) sum += n

jshell> sum
sum ==> 55

jshell> sum = 0
sum ==> 0

jshell> for (int i = 0; i < a.length; i++) sum += a[i]

jshell> sum
sum ==> 55

拡張 for 文の場合、配列 a の要素を先頭から順番に取り出して変数 n にセットします。通常の for 文の場合は、変数 i を 0 に初期化して、更新処理で i を +1 していくことで、配列の先頭から順番にアクセスします。条件部で i の値が a.length 以上になったならば、配列の範囲を超えるので繰り返しを終了します。このような単純な処理の場合は拡張 for 文の方が簡単ですね。

●繰り返しの制御

while 文や for 文は break 文によって繰り返しを脱出することができます。contiune 文は繰り返しの先頭に戻ります。break 文と continue 文の動作を図 4 に示します。

//
// break と continue
//
while (testA) {←──────┐
    処理A;                   │
    if (testB) continue; ──┘
    処理B;
    if (testC) break;───┐
    処理C;                 │
}                          │
 ←────────────┘
処理D;

図 4 : break 文と continue 文の動作

testB が真で continue 文が実行されると、それ以降の処理を実行せずに条件部のチェックが行われます。つまり、処理 B, testC, 処理 C は実行されません。for 文で continue 文が実行されると、それ以降の処理は実行されずに更新処理が実行されます。拡張 for 文の場合は次の要素を取り出す処理が行われます。

testC が真で break 文が実行されると、それ以降の処理を実行せずに while 文や for 文の繰り返しを脱出します。図 4 では、break 文で while 文の繰り返しを脱出すると、while 文の次の処理 D が実行されます。

ここまではC/C++と同じですが、Java の break 文は後ろにラベルを付けることができます。そして、同じラベルの処理へ脱出することができます。これは多重ループから脱出するときに使うと便利です。

●コマンドライン引数の取得

Java の場合、メソッド main で指定した String 型の配列にコマンドラインで与えられた引数が格納されています。次のリストを見てください。

リスト : コマンドライン引数の取得

public class sample24 {
  public static void main(String[] args) {
    for (String a: args) {
      System.out.println(a);
    }
  }
}

変数 args の内容を表示するだけです。3 つの引数を与えて起動すると、次のように表示されます。

$ javac sample24.java
$ java sample24 foo bar baz
foo
bar
baz

●素数を求める

簡単な例題として、100 以下の素数を求めるプログラムを作ってみましょう。いちばん簡単な方法は、奇数 3, 5, 7, 9, ... をそれまでに見つけた素数で割ってみることです。見つけた素数は配列に格納しておけばいいでしょう。プログラムは次のようになります。

リスト : 素数を求める

public class Prime {
  public static void main(String[] args) {
    int primeTable[] = new int [100];
    int primeSize = 1;
    primeTable[0] = 2;
    for (int n = 3; n < primeTable.length; n += 2) {
      boolean flag = true;
      for (int i = 1; i < primeSize; i++) {
        int p = primeTable[i];
        if (p * p > n) {
          break;
        } else if (n % p == 0) {
          flag = false;
          break;
        }
      }
      if (flag) primeTable[primeSize++] = n;
    }
    for (int i = 0; i < primeSize; i++) {
      System.out.print(primeTable[i] + " ");
    }
  }
}
$ javac Prime.java
$ java Prime
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

変数 primeTable は素数を格納する配列で 0 番目の要素を 2 に初期化します。変数 primeSize は格納されている素数の個数を表します。変数 n を 3 に初期化して、for ループで n の値を 2 ずつ増やしていきます。これで奇数列を生成することができます。

このプログラムは変数 flag の使い方がポイントです。for ループの先頭で flag を true に初期化します。次の for ループで、primeTable に格納されている素数を取り出して変数 p にセットします。n は奇数なので、2 で割り算する必要はありません。primeTable の 1 番目の要素から順番に primeSize - 1 番目までの要素を調べます。

n が素数か判別する場合、実際には primeTable の素数をすべて調べる必要はなく、√n より小さい素数を調べるだけで十分です。p > √n のかわりに p * p > n をチェックし、真であれば break で for ループを脱出します。x % y が 0 ならば、flag を false にセットしてから break で for ループを脱出します。

そして、for ループが終了した後、flag が true であれば n を primeTtable に追加して、primeSize の値を +1 します。これで、primeTable の先頭から順番に素数を格納していくことができます。最後に for ループで求めた素数を表示します。

ところで、今回のプログラムはちょっとわかりにくいのが欠点です。この場合、関数 (メソッド) を使うとわかりやすいプログラムを作ることができます。

●エラトステネスの篩

もう一つ、素数を求める簡単な方法を紹介しましょう。最初に、2 から N までの整数列を生成します。先頭の 2 は素数なので、この整数列から 2 で割り切れる整数を取り除き除きます。2 で割り切れる整数が取り除かれたので、残った要素の先頭が素数になります。先頭要素は 3 になるので、今度は 3 で割り切れる整数を取り除けばいいのです。このように、素数を見つけたらそれで割り切れる整数を取り除いていくアルゴリズムを「エラトステネスの篩 (ふるい)」といいます。

プログラムは次のようになります。

リスト : エラトステネスの篩

public class Sieve {
  public static void main(String[] args) {
    // false は素数, true は素数ではない
    boolean primes[] = new boolean [100];
    for (int n = 2; n < primes.length; n++) {
      if (primes[n]) continue;  // n は素数ではない
      // n の倍数を削除
      for (int m = 2 * n; m < primes.length; m += n) {
        primes[m] = true;
      }
      // 表示
      System.out.print(n + " ");
    }
  }
}
$ jvavac Sieve.java
$ java Sieve
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

boolean 型の配列 primes で整数列を表します。false で素数を表し、素数でない場合は true をセットします。boolean 型の配列は false で初期化されるので、最初はすべての数が素数ということになります。次に、for ループで primes から素数 n を探します。n = 2 の場合、primes[n] は false なので n は素数になります。primes[n] が true の場合は continue で for ループの更新処理へ移ります。

n が素数の場合は、次の for ループで primes から n の倍数を取り除きます。変数 m を 2 * n に初期化し、for ループの更新処理で m に n を加算していけば、m の値は n の倍数になります。あとは primes[m] に true をセットして、素数 n を表示するだけです。

なお、このプログラムは改善の余地があります。奇数だけを調べるように工夫すると、配列の大きさを半分にすることができ、実行時間も速くなるでしょう。興味のある方はプログラムを改造してみてください。

●素因数分解

エラトステネスの篩と同じ考え方で素因数分解を行うことができます。素因数分解とは、素数でない整数 (合成数) を素数の積の形に書き表すことです。たとえば、12 は 2 * 2 * 3 と素因数分解することができます。プログラムは次のようになります。

リスト : 素因数分解

public class Factorization {
  public static void main(String[] args) {
    int m = 1234567890;
    // 2 で割れるだけ割り算する
    while (m % 2 == 0) {
      System.out.print(2);
      System.out.print(" ");
      m /= 2;
    }
    // 奇数で割り算していく
    for (int i = 3; i * i <= m; i += 2) {
      while (m % i == 0) {
        System.out.print(i + " ");
        m /= i;
      }
    }
    if (m > 1) System.out.println(m);
  }
}

最初に 2 で割り算します。それから、奇数で割り算していきます。割り算するときは、その数で割り切れるあいだは割り算を続けることに注意してください。たとえば、27 を素因数分解すると 3 * 3 * 3 になりますが、3 を一回だけしか割り算しないと、結果は 3 * 9 のように素数ではない数が含まれてしまいます。

実行結果は次のようになります。

$ javac Factorization.java
$ java Factorization
2 3 3 5 3607 3803

どの数も素数で、2 * 3 * 3 * 5 * 3607 * 3803 を計算すると 1234567890 になります。なお、これはとても単純なアルゴリズムなので、大きな整数の素因数分解には適していません。巨大な合成数の素因数分解はとても難しい問題です。興味のある方は素因数分解について調べてみてください。

●switch 文

ひとつの値を比較して条件分岐を行う場合は if 文よりも switch 文を使ったほうが簡単です。Java の switch 文はC/C++とほぼ同じです。switch 文の構文を示します。

  switch (式) {
  case A:
    処理A1;
    処理A2;
    処理A3;
    break;
  case B:
    処理B1;
    処理B2;
    処理B3;
    break;
  case C:
    処理C1;
    処理C2;
    処理C3;
    break;
  default:
    処理Z1;
    処理Z2;
    処理Z3;
  }

  図 5 : case の構文

switch 文は最初に ( ) の中の式を評価します。式の評価結果は文字型を含む整数値 [*1] でなければいけません。そのあとに複数の case 節が続きます。case の後ろには定数値 (整数値) を指定します。そして、式の評価結果と case で指定した定数を比較します。

式の評価結果と等しい値を見つけた場合、その case 節以降の処理を順番に実行して、break 文で実行を中断します。break 文を忘れると、次の case 節の処理も実行してしまいます。ご注意くださいませ。そうでなければ、次の case 節に移ります。たとえば、定数 A と等しくない場合、次の節に移り定数 B をチェックします。

もしも、等しい定数が見つからない場合は default 節が実行されます。なお、default 節は省略することができます。switch 文の動作を図 6 に示します。


          図 6 : switch 文の流れ図

簡単な例を示します。switch 文を使って FizzBuzz 問題を解いてみましょう。次のリストを見てください。

リスト : FizzBuzz 問題 (2)

public class FizzBuzz1 {
  public static void main(String[] args) {
    for (int i = 1; i <= 100; i++) {
      switch (i % 15) {
      case 0:
        System.out.print("FizzBuzz");
        break;
      case 3: case 6: case 9: case 12:
        System.out.print("Fizz");
        break;
      case 5: case 10:
        System.out.print("Buzz");
        break;
      default:
        System.out.print(i);
      }
      if (i % 20 == 0) {
        System.out.println();
      } else {
        System.out.print(" ");
      }
    }
  }
}
$ javac FizzBuzz1.java
$ java FizzBuzz1
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz
Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz
41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz
Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz

switch 文で i % 15 を求めます。0 であれば 15 で割り切れるので、FizzBuzz を表示します。3, 6, 9, 12 であれば、3 の倍数なので Fizz と表示します。リスト 9 のように複数の case を続けて設定してもかまいません。5, 10 であれば 5 の倍数なので Buzz と表示します。それ以外の数値は default で i を表示します。

-- note --------
[*1] switch 文は JDK 5 から整数値だけではなく enum 型 (列挙型) も指定できるようになりました。

●問題

  1. 九九表を出力するプログラム NinetyNine.java を for 文を使って書き直してください。
  2. 下記に示すデータの度数分布表と累積度数表を求めるプログラム Frequency.java を作ってください。
    リスト : 身長のデータ
    
    double height[] = {
      148.7, 149.5, 133.7, 157.9, 154.2, 147.8, 154.6, 159.1, 148.2, 153.1,
      138.2, 138.7, 143.5, 153.2, 150.2, 157.3, 145.1, 157.2, 152.3, 148.3,
      152.0, 146.0, 151.5, 139.4, 158.8, 147.6, 144.0, 145.8, 155.4, 155.5,
      153.6, 138.5, 147.1, 149.6, 160.9, 148.9, 157.5, 155.1, 138.9, 153.0,
      153.9, 150.9, 144.4, 160.3, 153.4, 163.0, 150.9, 153.3, 146.6, 153.3,
      152.3, 153.3, 142.8, 149.0, 149.4, 156.5, 141.7, 146.2, 151.0, 156.5,
      150.8, 141.0, 149.0, 163.2, 144.1, 147.1, 167.9, 155.3, 142.9, 148.7,
      164.8, 154.1, 150.4, 154.2, 161.4, 155.0, 146.8, 154.2, 152.7, 149.7,
      151.5, 154.5, 156.8, 150.3, 143.2, 149.5, 145.6, 140.4, 136.5, 146.9,
      158.9, 144.4, 148.1, 155.5, 152.4, 153.3, 142.3, 155.3, 153.1, 152.3
    };
    
       階級   度数 累積度数
    ------------------------
    130 - 135   1      1
    135 - 140   6      7
    140 - 145  12     19
    145 - 150  25     44
    150 - 155  32     76
    155 - 160  17     93
    160 - 165   6     99
    165 - 170   1    100
    

階級はデータの範囲を表します。この表では x cm 以上 y cm 未満を x - y で表しています。度数はその階級に出現したデータの個数です。度数を示してある表のことを「度数分布表」といいます。累積度数はその階級までの度数を全部加えたものです。累積度数を示してある表を「累積度数分布表」といいます。













●解答1

リスト : 九九表

public class NinetyNine1 {
  public static void main(String[] args) {
    System.out.println("   |  1  2  3  4  5  6  7  8  9");
    System.out.println("---+---------------------------");
    for (int i = 1; i <= 9; i++) {
      System.out.print(" " + i + " | ");
      for (int j = 1; j <= 9; j++) {
        int k = i * j;
        if (k < 10) {
          System.out.print(" " + k + " ");
        } else {
          System.out.print(k + " ");
        }
      }
      System.out.println("");
    }
  }
}
$ javac NinetyNine1.java
$ java NinetyNine1
   |  1  2  3  4  5  6  7  8  9
---+---------------------------
 1 |  1  2  3  4  5  6  7  8  9
 2 |  2  4  6  8 10 12 14 16 18
 3 |  3  6  9 12 15 18 21 24 27
 4 |  4  8 12 16 20 24 28 32 36
 5 |  5 10 15 20 25 30 35 40 45
 6 |  6 12 18 24 30 36 42 48 54
 7 |  7 14 21 28 35 42 49 56 63
 8 |  8 16 24 32 40 48 56 64 72
 9 |  9 18 27 36 45 54 63 72 81

●解答2

リスト : 度数分布表

public class Frequency {
  static double height[] = {
    148.7, 149.5, 133.7, 157.9, 154.2, 147.8, 154.6, 159.1, 148.2, 153.1,
    138.2, 138.7, 143.5, 153.2, 150.2, 157.3, 145.1, 157.2, 152.3, 148.3,
    152.0, 146.0, 151.5, 139.4, 158.8, 147.6, 144.0, 145.8, 155.4, 155.5,
    153.6, 138.5, 147.1, 149.6, 160.9, 148.9, 157.5, 155.1, 138.9, 153.0,
    153.9, 150.9, 144.4, 160.3, 153.4, 163.0, 150.9, 153.3, 146.6, 153.3,
    152.3, 153.3, 142.8, 149.0, 149.4, 156.5, 141.7, 146.2, 151.0, 156.5,
    150.8, 141.0, 149.0, 163.2, 144.1, 147.1, 167.9, 155.3, 142.9, 148.7,
    164.8, 154.1, 150.4, 154.2, 161.4, 155.0, 146.8, 154.2, 152.7, 149.7,
    151.5, 154.5, 156.8, 150.3, 143.2, 149.5, 145.6, 140.4, 136.5, 146.9,
    158.9, 144.4, 148.1, 155.5, 152.4, 153.3, 142.3, 155.3, 153.1, 152.3
  };

  public static void main(String[] args) {
    int m = 8, low = 130, z = 5;
    var freq = new int [m];  // 度数分布表
    var cum  = new int [m];  // 累積度数表
    // 度数分布表の作成
    for (var x: height) {
      for (int j = 0; j < m; j++) {
        if (x < low + z * (j + 1)) {
          freq[j]++;
          break;
        }
      }
    }
    // 累積度数表の作成
    cum[0] = freq[0];
    for (int i = 1; i < m; i++)
      cum[i] = cum[i - 1] + freq[i];
    // 表示
    for (int i = 0; i < m; i++) {
       System.out.print((low + z * i) + " - " + (low + z * (i + 1)));
       System.out.println(" | " + freq[i] + " \t" + cum[i]);
    }
  }
}
$ javac Frequency.java
$ java Frequency
130 - 135 | 1   1
135 - 140 | 6   7
140 - 145 | 12  19
145 - 150 | 25  44
150 - 155 | 32  76
155 - 160 | 17  93
160 - 165 | 6   99
165 - 170 | 1   100

初版 2009 年 4 月 4 日
改訂 2016 年 11 月 12 日
改訂二版 2021 年 2 月 7 日

Copyright (C) 2009-2021 Makoto Hiroi
All rights reserved.

[
PrevPage | Java | NextPage ]