Search code examples
javaarithmeticexception

Cannot work around ArithmeticException? / by zero?


I'm having trouble working around an ArithmeticException I'm getting from my getAverageScore() method in my Student class. I'm trying to write a program that reads the following text file scores.txt:

34     c081 c082 c083 c084
S2023  99   75   85   62
S2025  -1   92   67   52
S1909  100  83   45   -1

The c numbers such as c081 are course codes at the school, and the s numbers such as s2023 are student numbers. The figures in the middle represent their scores, the -1 also means they weren't enrolled in the unit.

I want to be able to write a program where I can give output as the student with the highest average across their classes, with that average and their student number. I want to be able to make sure the -1 values aren't included in that class average, so that if a student has one of those, their average is only calculated for the classes they did actually take.

This is the Student class:

import java.util.ArrayList;

public class Student {

    private String studentNumber;
    private ArrayList<Integer> scores = new ArrayList<Integer>();

    public Student(String studentText) {
        String[] parts = studentText.split(studentText, ' ');
        this.studentNumber = parts[0];

        for (int i = 1; i < parts.length - 1; i++) {
            scores.add(Integer.parseInt(parts[i + 1]));
        }
    }

    public String getStudentNumber() {
        return this.studentNumber;
    }

    public float getAverageScore() {
        int sum = 0;
        int numberOfCoursesNotTaken = 0;

        for (int i = 0; i <this.scores.size(); i++) {
            if (i != -1) {
            sum += this.scores.get(i);
            System.out.println(sum);
            } else {
                numberOfCoursesNotTaken++ ;
                System.out.println(numberOfCoursesNotTaken);
            }
        }
        return sum / (this.scores.size() - numberOfCoursesNotTaken);
    }


}


I'm calling this method from the following class:

import java.io.File; 
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class MySchool {
    public static void main(String[] args) {
        int numberOfStudents;
        ArrayList<Student> allStudents = new ArrayList<Student>() ;

        try {

            File scoresFile = new File("Scores.txt");
            Scanner scoresFileReader = new Scanner(scoresFile);


            String headerRow = scoresFileReader.nextLine();

            char c = headerRow.charAt(0);
            numberOfStudents = Character.getNumericValue(c);  


            for (int studentI = 0; studentI < numberOfStudents; studentI++) {
                String studentText = scoresFileReader.nextLine();
                System.out.println(studentText);
                Student student = new Student(studentText);
                allStudents.add(student);
            }

            scoresFileReader.close();

        } catch (FileNotFoundException e) {
            System.out.println("An error occurred");
            e.printStackTrace();
        }

        float highestAverage = 0;
        String highestScoringStudentNumber = null;


        for (Student student : allStudents) {
            if (student.getAverageScore() > highestAverage) {
                highestAverage = student.getAverageScore();
                highestScoringStudentNumber = student.getStudentNumber();
            }

        }
        System.out.println("Highest scoring student: " + highestScoringStudentNumber);
    }
}

However, the return line of getAverageScore() in Student gives the following error: Exception in thread "main" java.lang.ArithmeticException: / by zero at Student.getAverageScore(Student.java:34) at MySchool.main(MySchool.java:42)

I thought I'd solved this issue using the numberOfCoursesNotTaken variable? Could anyone help me?


Solution

  • I really recommend removing invalid values as soon as they are found. You could replace your Student constructor by the following:

    public Student(String studentText) {
        String[] parts = studentText.split(" "); // previously (studentText, ' ')
        this.studentNumber = parts[0];
    
        for (int i = 1; i < parts.length - 1; i++) {
            int score = Integer.parseInt(parts[i]); // NOT i+1
            if (score >=0) this.scores.add(score);
        }
    }
    

    While you are at it, you can greatly simplify your average-score calculation (now that there are no -1s):

    public float averageScore() {
       if (scores.isEmpty()) {
          return 0; // avoids divide-by-zero
       } else {
          int total = 0;
          for (int score : scores) total += score;
          return total / (float) scores.size();
       }
    }