Home > Net >  Counting occurrences of an array element - Index out of bounds error but the index number and out of
Counting occurrences of an array element - Index out of bounds error but the index number and out of

Time:09-02

So I'm having some issues with code I'm writing for an assignment and it's kinda driving me crazy. It's my first semester and I've never done coding before, so I know I still have heaps to learn. Anyways, the issues:

I'm having two problems which could be related but I'm not 100% sure. I'm getting this error:

'Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 125 out of bounds for length 125.'

Which points to the following section of code (Commented on specific line):

public static String gradesDistn() {
    String gradeDistn = "0";
    
    //Sort the above letterGrade array
    Arrays.sort(letterGrade);
    
    //This loop counts each occurrence of an element in the letterGrade array.
    for (int i = 0; i < letterGrade.length - 1; i  ) {
        int count = 0;
        for(int j = i   1; j < letterGrade.length; j  ) {
            if  (letterGrade[i] == letterGrade[j]) 
                count  ;
                
        System.out.println (gradeDistn = letterGrade[i]   ": "   count); //THIS IS THE ERROR LINE.
        i  = (count-1);
        }
    }  
    return gradeDistn;

I can post the full code if additional context is needed. Essentially I'm am trying to count the occurrences of each letter grade (A, B, C, D, E and F) which are stored in an array. Each occurrence is based off of another array which stores number marks and is randomly generated. So the results should look something like this:

A: 6

B: 10

C:20

D: 9

E: 3

F: 1

instead I'm getting (copied from console):

A: 1

A: 2

A: 3

A: 4

B: 5

B: 6

B: 7

B: 8

B: 9

B: 10

B: 11

C: 11

C: 11

D: 11

D: 11

F: 11

C: 20

D: 9

E: 3

F: 1

I've spent so long looking at these code and trying to make it work, I feel like I'm am blind to the potentially obvious issues with it. Any help on this 2 issues would be really appreciated!

Also of note: The assignment requires a bunch of super specific methods such as this so that can't be changed, addition classes can not be used etc.

CodePudding user response:

For this answer, I'm going to put aside the question of ArrayIndexOutOfBoundsException and offer guidance on how to generate a frequency distribution.

I will aim toward having an array of counters. Each counter will represent a value or range of values.

For this example, I want to analyze daily high temperatures. I decide to group by 10 degrees Fahrenheit. I could decide on 5 degrees, 7 degrees, or some other interval. It could even be irregular intervals. But, keeping it regular and going by 10 degrees makes the example easier to follow.

Having settled on grouping by 10 degrees, I next want to decide the maximum and minimum. I'll pick -19 as the coldest, and 119 as the hottest. But, I want to allow for occurrences outside of that range. So, to hold the count, I will want an array of 15 counters.

Next, I will want a means of "translating" a temperature measurement to an array index. I use the int variable k for that in the following code. To make it easier to follow, I broke the calculation into 4 lines and then used the result as a subscript:

public static int [] tempFreqDist (WeatherStats [] daily) {
    int [] count = new int [15];  // java initializes to zeros
    int k;
    for (int dIdx = 0; dIdx < daily.length;    dIdx) {
          k = daily [dIdx].getHighTemp();
          k = Math.max (k,-20);
          k = Math.min (k,120);
          k = k/10   2;
          count [k]  ;
    }    
    return count;
}

We want to group temps of -20 and colder together, regardless of how far below -20. So, we use Math.max. Similarly, we group temps of 120 and hotter by using Math.min. Next, divide by our grouping factor, and adjust the result so the lowest has 0 for the subscript value.

So, the result is the elements of count correspond to the temperature ranges: 0 ➔ -20 and colder; 1 ➔ "teens" (10 to 19) below zero; 2 ➔ single digits below zero; 3 ➔ zero and single digits above; 4 ➔ teens above zero; 5 ➔ twenties, ..., 14 ➔ teens above 100; 14 ➔ 120 and above.

But, suppose the 'width' of categories was irregular? One possibility is that you could use a chain of if ... else:

int t = daily [dIdx].getHighTemp();
if (t <= -20) k = 0;
else if (t <= -13) k = 1;
else if (t <= 0) k = 2;
else if (t <= 15) k = 3;
else if (t <= 28) k = 4;

and so on.

The chain of if ... else can be used for letter grades:

 public int[] gradeFD (char [] letterGrade) {
    int [] count = new int [6]; 
      // 0 ➔ A, 1 ➔ B, 2 ➔ C, 3 ➔ D, 4 ➔ E, 5 ➔ F 
    ...
    for (int m = 0; m < letterGrade.length;   m) {
       if (letterGrade[m] == 'A') count[0]  ;
       else if (letterGrade[m] == 'B) count [1]  ;
       else if ... 

But, for something like letter grades, I prefer switch to if ... else chain:

public static int [] gradeFD (char [] letterGrade) {
    int [] count = new int [6];
    for (int m = 0; m < letterGrade.length;   m) {
        switch (letterGrade [m]) {
            case 'A': 
                count[0]  ;
                break;
            case 'B':
                count [1]  ;
                break;
            case 'C':
                count [2]  ;
                break;
            case 'D':
                count [3]  ;
                break;
... 

There's a "trick" you can use to easily convert a letter to an index. Recall that a char is essentially a integer primitive: You can do numeric calculations on it.

 char letter;
 int idx;
 ...
 if (letter >= 'A' && letter <= 'Z') { 
    idx = letter - 'A'; // result is zero to 25
 ... 

This takes advantage of the fact that the letters A to Z are consecutive in character set encoding. However, that isn't universal. EBCDIC, for example, has non-letter characters between I and J, and between R and S, IIRC.

CodePudding user response:

Simple Technic if you understand this, you can solve so many problems with this method. Creating a other array with the same size of user giving Array    
     {
                  int[] a = { 1, 2, 3, 4, 5, 1, 2, 3, 7, 8 };
                  //create a Array with of a[]
                  int[] b = new int[a.length];

                  for (int i = 0; i < a.length; i  ) {
                        //set count =1 in every new array element taken.
                        int count = 1;
                        for (int j = i   1; j < a.length; j  ) {
                              if (a[i] == a[j]) {
                                    count  ;
                                    
                                    b[j] = -1;

                              }
                              
                              if (b[i] != -1) {
                                    //put count value into Second Array if its not -1;
                                    b[i] = count;
                              }
                        }
                  }
                  for (int i = 0; i < a.length; i  ) {
                        if (b[i] != -1) {
                              System.out.println(a[i]   " "   b[i]);
                        }
                  }

            }
      }
}
  • Related