1. ホーム
  2. java

[解決済み] アスタリスクを用いたJavaヒストグラム

2022-02-11 01:58:50

質問

プログラムを実行するアプリケーションを利用したヒストグラムクラスを作成しようとしています。

 public class Histogram
{
   String name;
   int max;


   public Histogram (String name, int max)
   {
      this.name = name;
      this.max = max;
   }

   int[] count = new int[max+1];

   public void add(int numbers) 
   {
    // Handles out of bounds case
    if (numbers < 0 || numbers > max)
        return;

    count[numbers]++;
   }

   public String toString()
   {
      String result = name + "\n";
      for (int index = 0; index < count.length; index++)
      {
      result = result + count[index] + ": ";
         for (int indexStar = 0; indexStar < count[index]; indexStar++)
            result = result + "*";
         result = result + "\n";
         }
         return result;
   }
}

私のアプリケーションです。

public class HistogramDataCollector
{
   public static void main (String[] args)
   {
      Histogram h = new Histogram ("Favorite Number Survey", 11);

      h.add(1); h.add(0); h.add(9); h.add(7); h.add(7);
      h.add(3); h.add(4); h.add(6); h.add(5); h.add(2);
      h.add(2); h.add(8);

      System.out.println(h);
   }
}

アスタリスクで作成したヒストグラムを整形するために、int型の数値を足して出現頻度を求める方法がわからず、悩んでいます。 ありがとうございます。

どのように解決するのですか?

まず最初にやるべきことは、その余計な for ループコードは、クラス内のすべてのメソッドの外側にあります。 これでは、コードをコンパイルすることができません。 しかし、そのコードを削除すれば、このクラスはまっすぐに動作するはずです。 また numbers 配列は、このクラスでは使用されていません。 このクラスでは count 変数を使えば、その理由がわかるはずです。

また、もうひとつの注意点として、コンストラクタと変数の定義を以下のように変更する必要があります。

String name;
int max;
int[] count;

public Histogram(String name, int max) 
{
   this.name = name;
   this.max = max;
   this.count = new int[max+1];  
}

その理由は、以下の通りです。 max が想定されています。 0 このクラスのオブジェクトを作成したときに そのため、これはサイズ 1 を読み込んでも、それは変わりません。 max をコンストラクタで指定します。 そのため、これを未割り当てのままにしておき、次に配列 コンストラクタ内 .


ご指摘の通り、このヒストグラムクラスからその出現頻度を求める方法に戸惑っているようですね。 ヒストグラムが何であるかの定義を思い出してください。 ヒストグラムは データの中に見られる数字の頻度。 その count の配列は、あなたのクラスで 自動的に には、頻度、つまりデータセット内でその特定の数値を何回目にしたかが格納されます。 そのため add() このメソッドへの入力は、ヒストグラムに配置される数値を観察することです。

ヒストグラムがどのように機能するかの例として、もし count[0] = 1, count[1] = 2, count[2] = 4 を見た回数ということです。 0 は1回です。 1 2回、および 2 データセットに4回含まれています。したがって、各数値の頻度を取得するためには、 count 配列の各要素に対して繰り返し処理を行えばよいことになります。上の例では、テスタークラスでさまざまな add メソッドを呼び出した後、各数値の度数を取得することになります。 count[0] = 1, count[1] = 1, count[2] = 2, count[3] = 1, count[4] = 1, count[5] = 1, count[6] = 1, count[7] = 2, count[8] = 1, count[9] = 1, count[10] = 0 .

の各位置は count その数字を何度も見ることになります。 そのため add() メソッドを使用します。 numbers は見ている数字です。 そのため、その番号に属する特定のスロットにアクセスし、カウントを1つ増やします。 例えば、次のようにします。 h.add(0); は、次のようになります。 count[0]++; と同じです。 count[0] = count[0] + 1; . アクセススロット 0 で、1ずつインクリメントします。 1 の時間です。 以降の呼び出しについては h.add この場合、その番号をさらに1回見ることになる。

しかし、あなたのaddメソッド はエラーチェックを行いません。 . 具体的には、0 よりも小さい、または、0 よりも大きい数値を指定する必要があります。 max を取得します。 OutOfBoundsException ヒストグラムのビンをインクリメントしようとしたとき。 このような場合は,何もせずにメソッドから戻ることをお勧めします. 言い換えると

public void add(int numbers) {
    // Handles out of bounds case
    if (numbers < 0 || numbers > max)
        return;

    count[numbers]++;
}

クラス定義で int count[] = new int[max+1]; は、この配列のすべての要素に自動的に0を代入します。 max は、データセットに表示される可能性のある最も大きな数値になります。 必ず 1 を使用することで、0 インデックスを考慮することができます。 max+1 スロットを使用します。 これは、データセットに現れるあらゆる数の頻度を記録できるようにするためです。 このクラスからオブジェクトを作成すると、これらのビンはすべて 0 にリセットされるので、すぐにオブジェクトを使い始めることができます。


ひとつ注意したいのは、このヒストグラムをビンの数を表すアスタリスクを表示する形で実装したいとおっしゃっていたことです。 そのため toString() メソッドはこのようになります。

public String toString()
{
   String result = name + "\n";
   for (int index = 0; index < count.length; index++) {
       result = result + index + ": "; // New
       for (int indexStar = 0; indexStar < count[index]; indexStar++) // New
           result = result + "*"; // New
       result = result + "\n"; // New
   }
   return result;
}

上記のコードでは、ヒストグラムの各ビンについて、数値の頻度を表示し、コロンの後にスペースを入れ、その数値の頻度と同じ数のアスタリスクを配置します。 したがって、最初の例を考えてみると、次のようになります。

0: *
1: **
2: ****

頻度カウントがどのように見えるかを示しているだけであることに注意してください。 このクラスのオブジェクトをきちんと作っていないので、ヒストグラムの名前は未定義です。 しかし、ヒストグラムの度数カウントはこのように表示されるはずです。


これで質問が解決するといいのですが