1

I'm doing a java project at school and one of the tasks that I'm stuck on is correctly calculating and displaying the mean and median of rows and columns of a 2-D array. My code is in classes so I'll try to ask this question as clearly as possible. Here's my code:

//Main class
package com.company;
import java.io.*;

public class Main {

   public static void main(String[] args) {

       FileALL Free = new FileALL("src/com/company/text.txt");

       try{
           Free.FileRead();
           Free.Eraser();
           Free.Writing();
           Free.Meanie();
Free.Median();

       }

       catch (Exception e){
           e.printStackTrace();
       }
   }
}

//FILEALL Class (the class with all of the calculations, file I/O, etc.)

package com.company;

import java.io.*;
import java.util.Arrays;

public class FileALL {

   //Declare variables
   private static int row = 20;
   private static int col = 50;
   private int i;
   private int j;
   private int size;
   private int Mean;
   private int Median;
   private int elements;
   private static int RawData[][] = new int[row][col];
   private File f;

   //New method for use in the main class
   //Initialize the file

   public FileALL (String FileRead) {

       f = new File(FileRead);

   }

   //Method for file input
   public void FileRead () {

       try {

           BufferedReader reader = new BufferedReader(new FileReader(f));

           String line = reader.readLine();

           while ((line != null)) {

               String[] Values = line.trim().split("\\s+");

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

                   RawData[i][j] = Integer.parseInt(Values[j]);
                   System.out.print(RawData[i][j] + " ");
               }

               i++;
               System.out.println();
               line = reader.readLine();
           }

           reader.close();


       } catch (IOException e) {
           System.out.println("ERROR");
           System.exit(0);
       }

   }

   //This was a test for file output; I didn't really use it
    /*public void FileWrite () throws IOException {

       FileInputStream in = null;
       FileOutputStream oot = null;

       try {
           in = new FileInputStream("text.txt");
           oot = new FileOutputStream("OG_out.txt");

           int c;
           while ((c = in.read()) != -1){
               oot.write(c);
           }
       }finally {
           if (in != null){
               in.close();
           }
           if (oot != null){
               oot.close();
           }
       }

   }*/

   //Method for mean calculation
   public int Meanie (){

       int sum = 0;

       for (i = 0; i < row; i++){
           for (j = 0; j < col; j++){
               if (RawData [i][j] > 0){
                   sum += RawData[i][j];
                   size++;
               }
           }
       }

       if (size != 0) {
           Mean = (sum/size);
       }

       System.out.println("\nThe mean is " + Mean);

       return Mean;
   }

   //Median method
   public void Median (){

       //Make a separate 1-D array to store the items
       int [] list = new int[RawData.length*RawData[0].length];

       //Initialize a new integer to keep track of the position of the items in the 1-D array
       int Pos = 0;

       //Iterating over the 2-D array, now adding in the new list position integer
       for (i = 0; i < RawData.length; i++){
           for(j = 0; j< RawData.length; j++){
               list[Pos++] = RawData[i][j];
           }
       }

       //Sort the 1-D array
       Arrays.sort(list);

       elements = row - Pos;
       System.out.print("\nThe median is: " + MED(list));

   }

   //Separate method for Median
   public double MED(int[]m){

       int middle = m.length/2;

       if (m.length%2 == 1){
           return m[middle];
       }

       else {
           return (m[middle - 1] + m[middle]) / 2;
       }
   }

   //Method for Writing the means, medians, modes, and data sets of the array into a file created specifically for output (rows only)
   //Need to figure out how to withhold the zeroes from being printed

   public void Writing () throws IOException {

       BufferedWriter writer = new BufferedWriter(new FileWriter("src/com/company/OG_out.txt", true));
       writer.write("The mean of the input array is " + Mean + "\n\n");

       int a = 1;

       //I'm using 'i' here because 'i' is my integer for the row counter (for the sake of simplicity)

       for (i = 0; i < row; i++){
           writer.write("Data set " + a + ": " + Arrays.toString(RawData[i]) + "\n\n==================================================\n\n");
           writer.flush();
           a++;
       }
   }

   //This is a short method that will erase the data that was written into the output file
   public void Eraser () throws IOException {
       new BufferedWriter(new FileWriter("src/com/company/OG_out.txt", false));
   }

}



//Text.txt file (you can enter any set of numbers in a 2-D array fashion) 

1 2 3
5
6

I'm not getting any errors of exceptions but the mean sometimes comes up incorrect (which probably means it's always incorrect) and the median always comes up as 0.0. I'll also need to do the mode of the rows and columns but I don't know where to start (maybe I'll ask a separate question).

Thanks for reading and taking the time to help me out (if you choose to do so).

EDIT: I need a maximum of 20 rows and 50 columns. Also, I got the mean calculation working fine.

  • 1
    You have a typo in your double loop in `Median`. I don't know whether that's the cause of the problem, though. – ajb Apr 11 '16 at 00:17
  • What typo? Not sure if that would be the problem though. – Binary_Skywalk Apr 12 '16 at 18:15
  • I'll let you try to figure it out, but ask yourself: is your array square? That should give you a hint. However, based on my answer, finding the typo really doesn't matter since you'll need to redo that logic anyway. – ajb Apr 13 '16 at 03:08

2 Answers2

0

RawData.length is always 20 no matter how much data you actually enter. RawData[0].length is always 50. Once you allocate the array, you can't change the length downward even if you enter less data. So there will be a lot of unused elements in your array that Java initializes to 0. This means you can't use .length to loop over the array. You will need another way to tell your algorithm how many rows and columns you really have. Otherwise all those extra 0's will be part of the computation.

ajb
  • 31,309
  • 3
  • 58
  • 84
0

If you are retrieving your data from a text file with delimited line columns and the potential for basically an unspecified number of rows (file lines) then why are you declaring your RawData[][] 2D Array to a fixed number of elements when you don't really know yet what the max number of columns and rows are within the data file unless of course you are going to handle chunks of data which it does not appear you are doing. What if you have 22 or 30 lines of data in file? You'll end up with a Array Out Of Bounds Exception.

In my opinion, I think the best way to handle this if you must have a 2D Array and the data file will contain lines of varying data columns is to do a two pass read over the file.

The first pass would be used to determine the maximum number of columns in any one file line (row) and also determining the number of lines within the file which actually contain data (not a blank line - just in case it does). Determining the number of valid data lines within the data file will allow you to set the Row quantity of your 2D Array. By determining the maximum number of columns in any one line within the data file will allow you to set the Columns quantity of your 2D Array.

File f = new File("src/com/company/text.txt");
if (!f.exists()) { System.exit(0); }

// PASS 1
int maxColumns = 0;
int rows = 0;
String line = "";
try {
    BufferedReader reader = new BufferedReader(new FileReader(f));
    while((line = reader.readLine()) != null){
        if (!line.equals("")) {   
            String[] values = line.trim().split(" ");
            // Get the largest number of columns on any line in file.
            if (values.length > maxColumns) { maxColumns = values.length; }
            rows++;    
        }
    }
    reader.close();

} 
catch (IOException e) {
    System.out.println("IOException ERROR\n\n" + e.getMessage());
    System.exit(0);
}

// Declare and initialize the rawData[][] 2D Array.
Object[][] rawData = new Object[rows][maxColumns];

The second pass read over the file would be for applying the file data into their respective 2D Array elements and because you are dealing with varying columns I would declare the 2D Array as Object since the natural data type within a text file is String and a Object type allows you to determine if a specific array element contains 'null', however, if the 2D Array is declared as a numerical data type then a empty element would contain the numerical value of zero (0) which could be a valid data value in file. Since each column element within an Object 2D Array can contain a different data type we just need to load the required ones with our desired numerical data type and leave the ones we don't need as they are:

// PASS 2
rows = 0;
line = "";
try {
    BufferedReader reader = new BufferedReader(new FileReader(f));
    while((line = reader.readLine()) != null){
        if (!line.equals("")) {   
            String[] values = line.trim().split(" ");
            for (int i = 0; i < values.length; i++) {
                rawData[rows][i] = values[i];
            }
            rows++;    
        }
    }
    reader.close();

} 
catch (IOException e) {
    System.out.println("IOException ERROR\n\n" + e.getMessage());
    System.exit(0);
}

You can always convert the Array elemental data to the desired numerical data type when iterating through and retrieving elemental data within the array. For example:

for (int i = 0; i < rawData.length; i++) {
    for (int j = 0; j < rawData[0].length; j++) {
        // If the 2D Array element is empty then ignore it...
        if (rawData[i][j] != null) {   
            // otherwise get the elemental data.
            int num = (int) rawData[i][j];  //Cast the object to Integer.
            System.out.println("i = " + i + " | j = " + j + " | element contains: " + num);
            // .....................................
            // ... Do whatever you want with num ...
            // .....................................
        }
    }
}

Of course I show all this done within a single stream or method of code but it too can be moved into individual classes...that's for you to do.

I hope this helps in some way.

DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22