views:

1301

answers:

5

I'm taking a beginner Java class, with the assignment to create a histogram program with the following output: (100 and 10 are user inputs).

How many numbers? 100 How many intervals? 10

Histogram
--------------------------------------------------------
  1 ****(4)
  2 ******(6)
  3 ***********(11)
  4 *****************(17)
  5 **************************(26)
  6 *************************(25)
  7 *******(7)
  8 ***(3)
  9 (0)
 10 *(1)
--------------------------------------------------------

My code is giving the following output however, can anyone help me point out what is going wrong, thanks so much.

How Many Numbers? 10
How Many Intervals? 10

Histogram
--------------------------------------------------------
 1 **********(10)
 2 **********(10)
 3 **********(10)
 4 **********(10)
 5 **********(10)
 6 **********(10)
 7 **********(10)
 8 **********(10)
 9 **********(10)
 10 **********(10)

For the input, 100 and 10 I get the error message: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10 at Lab6.main(Lab6.java:44) I marked Line 44 below.

Which links to this code; intervalValue[j]++;

I'm not sure how to attach the generator (.jar) file, it is supposed to just generate the random #'s for us. Thanks again.

mport java.util.Scanner;

public class Lab6 {

    public static void main(String[] args) {

        int numbers, intervals;
        double intervalWidth;

        double max, mins, range;

        Scanner keyboard = new Scanner(System.in);

        System.out.print("How Many Numbers? ");

        numbers = keyboard.nextInt();

        System.out.print("How Many Intervals? ");

        intervals = keyboard.nextInt();

        double [] generate = new double[numbers];

        generate = randomGenerator(numbers);

        max = maximum(generate);

        mins = minimum(generate);

        range = max - mins;

        intervalWidth = range / intervals;

        int [] intervalValue = new int[intervals];

        for (int i=0; i < generate.length; i++) {

            for (int j = 0; j<generate.length; j++){
                double imin = mins+j*intervalWidth;
                double imax = max +j*(intervalWidth);
                if(generate[i] >= imin && generate[i] < imax)
                    intervalValue[j]++;         //LINE 44
            }
        }

        System.out.println("Histogram");

        System.out.println("--------------------------------" +
                           "------------------------");

        for (int a=0; a < intervalValue.length; a++) {

            System.out.print(" " + (a+1) + " ");

            for (int b=0; b < intervalValue[a]; b++) {
                System.out.print("*"); 
            }

            System.out.println("(" + intervalValue[a] + ")");
        }
    }

    private static double [] randomGenerator(int number) {
        double [] generate;

        generate = Generator.getData(number);

        return generate; 
    }

    private static double maximum(double [] a) {

        double max = a[0];

        for (int i = 1; i < a.length; i++) {        
            if (a[i] > max) {
                max = a[i];
            }         
        }

        return max;
    }

    private static double minimum(double [] a) {

        double mins = a[0];

        for (int i = 1; i < a.length; i++) {
            if (a[i] < mins) {
                mins = a[i];
            }
        }

        return mins;
    }
}
A: 

Use an IDE like eclipse, run your program and see where line 44 is. That's where you get your ArrayIndexOutOfBoundsException and that is where you need to make sure you are not going out of bonds. Arrays in java have there first item at index 0, so an array 10 items long will have them numbered 0,1,2,3,4,5,6,7,8,9. If it happens at 10, you are probably iterating one step to far. Make sure j in "intervalValue[j]" is not 10 when you get there.

Without neither the complete exception, source that compiles nor correct line numbers in the source you have pasted. There is not much more to do. Figuring it out will help you gain just as much knowledge as the rest of the lab will give you. Give it a good try.

Fredrik
+1  A: 

You need to remove the semicolon from the end of line 43:

if(generate[i] >= imin && generate[i] < imax);

The semicolon causes your if block to be empty. As a consequence, the line resulting in the exception is executed unconditionally.

Once you address that issue, here are a few hints to get you started on the further debugging of your code:


Take a look at the termination condition of your inner loop:

for (int j = 0; j<generate.length; j++)

You are iterating over the generated numbers in your outer loop; so you should be iterating over the intervals in your inner loop to determine the interval to which each generated number belongs.


Take a look at the code you are using to determine the bounds of the current interval in your loop:

double imin = mins+j*intervalWidth;
double imax = max +j*(intervalWidth);

These lines need to be modified to yield the correct values. Do a bit of 'pencil-and-paper debugging' to determine why they are currently in error.


I will leave the rest as an exercise for the reader for now. I will check back in later to see if you need any further assistance.

Brandon E Taylor
+1 Good spot, missed it.
Fredrik
A: 
intervalValue[j]++;

j comes goes up to the number of numbers but intervalValue is allocated from the number of intervals, if those two numbers are not the same you'll get the error you're seeing here.

Tom
How can I make them the same, or at least not create the error?-Thanks,
Benzle
A: 

Your array Exception appears to be caused by using generate.length twice - although, your pasted code seems to be edited from this.

However, aside from this, the issue lies in your nested loops. Apart from the wrong array size in the first of the inner loops, you're going along the right lines. Then, at the if statement - you want to increment that value, and that value alone if it's in the right interval; with your current code, you increment every one of them each time, which explains the output.

Taking your own code, and commenting:

for (int i=0; i < generate.length; i++) {

  for (int j = 0; j<intervals; j++){ // could use intervalValues.length here; it's all preference
    double imin = mins+j*intervalWidth;
    double imax = mins +(intervalWidth)*(j+1);
    if(generate[i] >= imin && generate[i] < imax) 
        // for(int j1 = 0; j1 < intervalValue.length; j1++) <- this was causing the bad output
        /* I assume the j1 from your code was during a debug attempt. Changed back,
           since the preceeding loop has been removed */
        intervalValue[j]++; 


  }

}
Farrell
A: 

Since I was feeling generous on a Saturday I tried it out and rewrote your loop.

for (int j=0; j < generate.length; j++) {
    for(int i = 0; i < intervals; i++) {
     double imin = mins + i * intervalWidth;
     double imax = mins + (intervalWidth) * (i + 1);
     if(i == intervals - 1) imax = Double.POSITIVE_INFINITY;
     if(i == 0) imin = Double.NEGATIVE_INFINITY;

     if (generate[j] >= imin && generate[j] < imax) {
      intervalValue[i]++;
      break;
     }
    }
}

The infinity stuff is to catch the min and maxes in the histogram.

Kekoa
Thanks everyone so much, this has been a great first experience on stack overflow!
Benzle