Array algotirhms for group operations

Lesson content

  • About algorithms for group operations on array elements
  • Summation, multiplication, average value of array elements
  • Finding the maximum or minimum value in an array
  • Most common errors

About algorithms for group operations on array elements

In previous lessons, algorithms for adding elements to an array, searching, modifying, and deleting have been covered. These are indeed the most common actions performed on array elements. However, it is also very common to perform some group operations on array elements. In the lesson about searching, one of these operations was already covered: counting elements in an array (which have certain characteristics). Now other commonly used group operations will be addressed.

Summation of array elements (sum) is a common operation on arrays that contain integers or real numbers as elements (or if from each array element some number can be extracted as an indicator). For example, summing all monthly profits from an array to calculate the total annual profit. Or, if each array element is a word (String), summing the number of letters in each word to get the total text length. Summation can also be combined with searching, so that it does not include all values in the array, but only some, e.g., summing only profits greater than 10,000.

Multiplication of array elements is also a common operation on arrays containing numbers (or if from each element a number can be extracted). For example, multiplying all coefficients in an array to calculate the total coefficient. This operation can be done on all array elements or only on a selected subset.

Calculating the average value of array elements (mean or average) is also common and can only be done on arrays that have numbers as elements (or if a number can be extracted from each element). As a reminder, the average is obtained by summing all elements of the array and dividing by the number of those elements. For example, calculating the average grade of students on an exam. This operation can be applied on all elements or only on selected elements, always dividing by the number of elements included in the selection or summation.

Finding the maximum or minimum value in an array means exactly that: finding the value in the array which is highest (maximum) or lowest (minimum) compared to others. For example, finding the highest profit during the year or the lowest exam grade.

This operation is not limited to arrays containing numbers or numerical indicators, but can also be applied to arrays containing letters. In that case, determining which element is “greater” or “less” is done by lexicographical comparison of array elements, e.g., the letter ‘B’ is “greater” than ‘A’ because it comes after it in the alphabet. Technically, the ASCII or UTF8 codes of these characters are compared (65 for capital ‘A’, 66 for capital ‘B’). Similarly, for arrays of Strings, two Strings can be compared by length (the longer String is “greater”) or by content (comparing the first letters, then the second letters, etc.), but this will be covered in the lesson about the String class.

Besides these operations, often some statistical indicators (quartiles, median, mode, standard deviation, etc.) are required on array values, but these will not be covered here because they are much easier to calculate using statistical and other data processing tools, or even additional Java libraries that already have these algorithms implemented.

Algorithmically, these operations do not imply changing the values of array elements, so all types of loops can be used, and other characteristics of these algorithms are:

  • The values of array elements are not changed, only a new value is produced based on values of multiple elements.
  • Usually, an auxiliary variable is used which contains the current result of the operation and is updated during the array traversal.
  • Algorithms may include selection before the operation, i.e., performing the operation only on those elements that have a certain value or characteristic.

Summation, multiplication, average value of array elements

Summation of array elements (sum) means going through the entire array (or up to the element count if the full capacity is not used) and adding one element at a time to the total sum during each iteration.

This means summation is done step by step, element by element. It also means that the intermediate sum result (while summing) must be stored in an auxiliary variable. In each iteration, the current array element value is added to the intermediate result or the auxiliary variable. The initial value of the auxiliary variable is zero because zero is the neutral value for addition — when a number (or numbers) is added to zero, it does not affect the sum result.

Example 1

Create a class MonthlyProfits which has:

  • An attribute profits which is an array of 12 real numbers. Each element of the array represents the profit for a specific month (January, February, …, December). The array should be immediately initialized with a capacity of 12.
  • A method enterProfit which takes as parameters a real number representing the profit and an integer representing the ordinal number of the month to which the profit refers (1 - January, 2 - February, …, 12 - December). The method inserts the appropriate profit value for that month into the array.
  • A method print which prints the profits for all months on the screen.
  • A method sum which sums the profits for all 12 months and prints the total annual profit on the screen.
  • A method sumLargeProfits which sums all large monthly profits (those greater than 200.0) and returns their sum as the return value.

Create a class TestMonthlyProfits which in the main method creates one object of the class MonthlyProfits, enters the profit for February which is 122.33, March 200.1, and May 255.44, prints all monthly profits on the screen, then the total annual profit, as well as the sum of all large monthly profits.

 1 class MonthlyProfits {
 2 
 3     double[] profits = new double[12];
 4 
 5     void enterProfit(double profit, int month){
 6         profits[month -1] = profit;
 7     }
 8 
 9     void print(){
10         for(int i = 0; i < profits.length; i++)
11             System.out.println(profits[i]);
12     }
13 
14     void sum(){
15         // Auxiliary variable to which
16         // monthly profits will be added
17         double totalProfit = 0;
18 
19         // Traversing through the array and adding each
20         // monthly profit to the total sum (totalProfit)
21         for(int i = 0; i < profits.length; i++)
22             totalProfit = totalProfit + profits[i];
23 
24         System.out.println("Total annual profit is: " + totalProfit);
25     }
26 
27     double sumLargeProfits(){
28         // Auxiliary variable to which
29         // large monthly profits will be added
30         double totalProfit = 0;
31 
32         // Traversing through the array and adding each
33         // monthly profit larger than 200 to the total
34         // sum (totalProfit)
35         for (double profit: profits)
36             if (profit > 200)
37                 totalProfit = totalProfit + profit;
38 
39         return totalProfit;
40     }
41 }
 1 class TestMonthlyProfits {
 2 
 3     public static void main(String[] args) {
 4         MonthlyProfits mp = new MonthlyProfits();
 5 
 6         mp.enterProfit(122.33, 2);
 7         mp.enterProfit(200.1, 3);
 8         mp.enterProfit(255.44, 5);
 9 
10         mp.print();
11 
12         mp.sum();
13 
14         System.out.println("Sum of large profits: "+mp.sumLargeProfits());
15     }
16 }

In the method sum, you can see how array elements are summed. It starts with a FOR loop whose counter goes from 0 to the length of the array minus 1. The auxiliary variable totalProfit is introduced so that in each iteration of the loop, the value of one monthly profit is added to this total sum, i.e., the total profit. The initial value of this variable is zero because zero is neutral for addition — adding zero to a number doesn’t affect the result. When the loop finishes, all monthly profits will be summed, and the result will be in the variable totalProfit (which is then printed on the screen). Specifically, all profits will be summed, most of which are zero except for February (122.33), March (200.1), and May (255.44), so the total annual profit will be 577.87.

In the method sumLargeProfits summation is performed with prior selection (only profits greater than 200). For a change, a FOR-EACH loop is used here because the array is used at full capacity anyway, and an IF statement is used for selection. The auxiliary variable totalProfit still starts at zero, and only those profits (array elements) greater than 200 are added to it. When the loop finishes, all large monthly profits will be summed, and the result will be in the variable totalProfit (which, unlike the previous method, is returned as the return value). Specifically, only the profits for March (200.1) and May (255.44) will be summed, so the total of large profits will be 455.54 (or 455.53999999999996 if Java has a floating-point addition error).

Multiplying array elements algorithmically proceeds similarly to summation, with the difference that:

  • Multiplication is performed with one element of the array in each iteration.
  • The initial value of the auxiliary variable is set to 1, because 1 is the “neutral” value for multiplication.

Selection before multiplication is also possible here, and attention should be paid to not exceeding the maximum allowed value for the data type during multiplication. For example, multiplying 1,000,000 by 3,000 would exceed the maximum value for the int type.

Example 2

Create a class FinancialCoefficients which has:

  • An attribute coefficients which is an array containing coefficients (e.g., 1.02).
  • An attribute counter which represents the number of actually entered values in the array. The initial value is zero.
  • A constructor that initializes the array coefficients with a capacity given as a parameter.
  • A method enterCoefficient which takes as parameter a real number representing the coefficient and inserts that value into the array in the first free spot. If the array is full, it just prints the message “ERROR” on the screen.
  • A method print which prints all entered coefficients on the screen.
  • A method multiply which multiplies all entered coefficients and returns their product as a return value.
  • A method multiplyNegatives which multiplies all entered coefficients that are less than zero and returns their product as a return value.

Create a class TestFinancialCoefficients which in the main method creates one object of class FinancialCoefficients, enters coefficients 1.1, -0.5, 0.8, and -0.2, then prints all coefficients on the screen, as well as their product and the product of negatives.

 1 class FinancialCoefficients {
 2 
 3     double[] coefficients;
 4     int counter = 0;
 5 
 6     FinancialCoefficients(int capacity){
 7         coefficients = new double[capacity];
 8     }
 9 
10     void enterCoefficient(double newCoefficient){
11         if (counter < coefficients.length){
12             coefficients[counter] = newCoefficient;
13             counter++;
14         }
15         else System.out.println("ERROR");
16     }
17 
18     void print(){
19         for(int i = 0; i < counter; i++)
20             System.out.println(coefficients[i]);
21     }
22 
23     double multiply(){
24         // auxiliary variable with which
25         // coefficients will be multiplied on by one
26         double totalCoefficient = 1;
27 
28         // Traversing through the array and multiplying
29         // each coefficient with the total coefficient
30         for(int i = 0; i < counter; i++)
31             totalCoefficient = totalCoefficient * coefficients[i];
32 
33         return totalCoefficient;
34     }
35 
36     double multiplyNegatives(){
37         // auxiliary variable with which
38         // coefficients will be multiplied on by one
39         double totalCoefficient = 1;
40 
41         // Traversing through the array and multiplying
42         // each negative coefficient with the total coefficient
43         for(int i = 0; i < counter; i++)
44             if (coefficients[i] < 0)
45                 totalCoefficient = totalCoefficient * coefficients[i];
46 
47         return totalCoefficient;
48     }
49 }
 1 class TestFinancialCoefficients {
 2 
 3     public static void main(String[] args) {
 4         FinancialCoefficients fc = new FinancialCoefficients(10);
 5 
 6         fc.enterCoefficient(1.1);
 7         fc.enterCoefficient(-0.5);
 8         fc.enterCoefficient(0.8);
 9         fc.enterCoefficient(-0.2);
10 
11         fc.print();
12 
13         System.out.println("All coefficients multiplied: " + fc.multiply());
14 
15         System.out.println("All NEGATIVE coefficients multiplied: " + fc.multiplyNegatives());
16     }
17 }

The method multiply shows the algorithm for multiplying array elements. It starts with a FOR loop whose counter goes from 0 to counter - 1 — because full array capacity is not used. If it went from 0 to length - 1 by accident, multiplication would almost always result in zero because “free” spots in the array are set to 0.0 (default value for double). For the same reason, a FOR-EACH loop should not be used here because it would multiply with “free” spots in the array — always resulting in zero.

The auxiliary variable totalCoefficient is introduced so that in each iteration of the loop, the value of one coefficient is multiplied to this total product. The initial value of this variable is 1 because one is the neutral value for multiplication. If zero were accidentally used as the initial value, the method would always return zero as a result (any number multiplied by zero is zero). When the loop finishes, all coefficients will be multiplied, and the result will be in the variable totalCoefficient.

In the method multiplyNegatives, multiplication of array elements is performed with prior selection (only negative coefficients). Here, a FOR loop is also used (loop counter from 0 to counter - 1), and an IF statement for selection. The auxiliary variable totalCoefficient still starts at 1, and only those coefficients (array elements) less than zero are multiplied with its value. After the whole loop finishes, the result is returned as the method’s return value.

Calculating the average value of array elements (also known as “mean”) comes down to summing all array elements (or all entered elements) and dividing by the number of summed elements. For example, if the average of grades 4, 5, 4, and 5 is required, first all four grades are summed, then divided by four (because four grades were summed). The average of grades 3, 4, and 5 is also calculated by summing those three grades and dividing by three:

1 average(4,5,4,5) = (4 + 5 + 4 + 5) / 4 = 18 / 4 = 4.5
2 
3 average(3,4,5) = (3 + 4 + 5) / 3 = 12 / 3 = 4

It can be noticed that the result is usually a real number, even though the array elements are integers, so auxiliary variables used for calculation should be defined as real (floating point) variables, not integers. Also, it’s important to check that the array is not “empty” because otherwise division by zero might occur.

Example 3

Create a class ExamGrades which has:

  • An attribute grades which represents students’ grades (for that exam). The grade is an integer in the range from 5 to 10.
  • An attribute counter which represents the current number of entered grades in the array. Its initial value is 0.
  • A constructor which takes as a parameter the number of students who registered for that exam and initializes the capacity of the grades attribute (array) to that number.
  • A method enterGrade which takes as parameter a grade on the exam and inserts it into the array in the first free spot.
  • A method print which prints all grades on the screen.
  • A method printAverageAll which prints on the screen the average grade of all grades for the exam.
  • A method printAveragePassed which prints on the screen the average grade of students who passed the exam (received a grade greater than 5).

Create a class TestExamGrades which in the main method creates one object of class ExamGrades with 12 students registered, and:

  • Enters grades 5, 10, 10, 7, and 8.
  • Prints all grades on the screen.
  • Prints the average grade of all students.
  • Prints the average grade of all students who passed the exam.
 1 class ExamGrades {
 2 
 3     int[] grades;
 4     int counter = 0;
 5 
 6     ExamGrades(int numberOfStudents){
 7         grades = new int[numberOfStudents];
 8     }
 9 
10     void enterGrade(int newGrade){
11         if (counter < grades.length) {
12             grades[counter] = newGrade;
13             counter++;
14         }
15         else System.out.println("No free space left");
16     }
17 
18     void print(){
19         for(int i = 0; i< counter; i++)
20             System.out.println(grades[i]);
21     }
22 
23     void printAverageAll(){
24         double sum = 0.0;
25 
26         for(int i = 0; i < counter; i++)
27             sum = sum + grades[i];
28 
29         if (counter == 0)
30             System.out.println("Array is empty");
31         else {
32             double averageAll = sum / counter;
33             System.out.println("Average grade of all students is: " + averageAll);
34         }
35     }
36 
37     void printAveragePassed(){
38         double sum = 0.0;
39         int passed = 0;
40 
41         for(int i = 0; i < counter; i++)
42             if (grades[i] > 5) {
43                 sum = sum + grades[i];
44                 passed++;
45             }
46 
47         if (passed == 0)
48             System.out.println("None of the students have passed the exam");
49         else {
50             double averagePassed = sum / passed;
51             System.out.println("Average grade of passed students is: " + averagePassed);
52         }
53     }
54 }
 1 class TestExamGrades {
 2 
 3     public static void main(String[] args) {
 4         ExamGrades eg = new ExamGrades(12);
 5 
 6         eg.enterGrade(5);
 7         eg.enterGrade(10);
 8         eg.enterGrade(10);
 9         eg.enterGrade(7);
10         eg.enterGrade(8);
11 
12         eg.print();
13 
14         eg.printAverageAll();
15 
16         eg.printAveragePassed();
17     }
18 }

The method printAverageAll in the first part sums all entered grades in the array, using a FOR loop whose counter goes from 0 to counter - 1. The auxiliary variable sum has an initial value of zero (neutral for addition), but note that the type of this variable is double, not int. Why? Because this sum will later be divided by the number of entered grades (counter, which is an int), and the result (average) is expected to be a real number. If two integers were divided (if both sum and counter were int), the average would be calculated using integer division (sum / counter), i.e., division without remainder, which would not be accurate in general.

After summing, it is checked whether the counter is greater than zero, to avoid the situation of division by zero (double averageAll = sum / counter), which would cause Java to throw an error. Finally, the average is calculated by dividing the sum by the counter and displayed on the screen.

In the method printAveragePassed, a similar algorithm is used, with the difference that:

  • Not all grades are summed, but only those greater than 5 (grades of students who passed the exam).
  • Only students with grades greater than 5 are counted (variable passed).
  • The average is calculated by dividing the sum of these students’ grades by the number of such grades (double averagePassed = sum / passed), and not by the total number of all entered grades.

Finding the maximum or minimum value in an array

It is often necessary to find the smallest or largest value in an array. For example, you might need to find the lowest monthly profit or the highest exam grade, and so on. This is done by comparing numbers, i.e., the values of the array elements. Number comparison is a natural comparison where the largest number represents the maximum, and the smallest number is the minimum. In the case where the array contains repeated numbers (duplicates) and, for example, two elements have the maximum value, the maximum is still equal to the value of one of them — it does not matter which one.

Algorithmically, finding the maximum involves searching the array with comparisons, such that whenever a value is found that is greater than all previously found values, it is declared the current maximum. As you continue through the array, if you find an even larger value, it replaces the previous maximum, and so on. An auxiliary variable is used to “memorize” the current maximum value while iterating through the array. After traversing the entire array, this auxiliary variable will hold the truly largest value of all the elements.

Finding the minimum is almost identical, except the auxiliary variable gets updated whenever an element smaller than the current minimum is found.

As the initial value for the auxiliary variable (maximum or minimum), you can take either:

  • The value of some element of the array (for example, the first one).
  • An “impossible” value that is smaller (for maximum) or larger (for minimum) than all possible values. For instance, if grades range from 1 to 5, and you want to find the highest grade, you might start with 0.
  • The smallest possible value for that data type (static constants like Integer.MIN_VALUE or Double.MIN_VALUE) if searching for a maximum.
  • The largest possible value for that data type (static constants like Integer.MAX_VALUE or Double.MAX_VALUE) if searching for a minimum.

Why is this done this way? Why can’t the starting value just be zero? If zero is used as the initial value when searching for a maximum, it can happen that all elements are negative numbers, so zero would incorrectly be considered the maximum even though it does not appear in the array.

Although these maximum and minimum search operations are usually related to numeric arrays, it is also possible to search for minimum or maximum in arrays of letters.

For example, suppose energy efficiency ratings of appliances are given as letters ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, or ‘F’ (where ‘A’ is the best and ‘F’ is the worst rating). If you have an array of energy efficiency ratings of several household appliances, then finding the most energy-efficient appliance reduces to finding the “minimum” letter in the array.

Why minimum and not maximum? Determining which energy efficiency rating is higher or lower comes down to lexicographical comparison of array elements. For example, letter ‘A’ is “less than” letter ‘B’ because it comes before it in the alphabet, ‘B’ is “less than” ‘C’ for the same reason, and so on.

Technically, the ASCII or UTF-8 codes of those characters are compared (65 for uppercase ‘A’, 66 for uppercase ‘B’, etc.), so the best rating ‘A’ has the smallest ASCII code, ‘B’ a slightly larger one, and so forth. Finding the best rating here means finding the letter with the smallest ASCII code — i.e., finding the “minimum.” If the best rating were ‘F’ and the worst ‘A’, then you would look for the “maximum.”

Example 4

Create a class PatientTemperatures which has:

  • An attribute temperatures which is an array holding multiple measurements of patients’ body temperatures in a hospital (e.g., 36.4). The array should be initialized immediately with capacity 10.
  • An attribute counter which counts the number of elements in the array. The initial value is zero.
  • A method enterTemperature that inputs a new temperature into the first free spot in the array, but only if there is space and if the temperature is between 33.5 and 41.5 degrees. Otherwise, the method prints “ERROR” on the screen.
  • A method findHighestTemperature that finds the highest patient temperature in the array and returns it as the return value. If the array is empty, the method returns -1.
  • A method findLowestTemperature that finds the lowest patient temperature in the array and returns it as the return value. If the array is empty, the method returns -1.
  • A method print which prints all the elements of the array in one line. If the array has no entered temperatures, it prints “Array is empty” on the screen.

Create a class TestPatientTemperatures which in the main method creates an object of the PatientTemperatures class and enters the temperatures 36.5, 39.1, and 35.7 into it. Then it should print all temperatures, and then the highest and lowest temperature.

 1 class PatientTemperatures {
 2 
 3     double[] temperatures = new double[10];
 4     int counter = 0;
 5 
 6     void enterTemperature(double newTemperature){
 7         if (counter < temperatures.length && newTemperature >= 33.5 && newTemperature <= 41.5) {
 8             temperatures[counter] = newTemperature;
 9             counter++;
10         }
11         else
12             System.out.println("ERROR");
13     }
14 
15     double findHighestTemperature(){
16         //If the array is empty, the method
17         // returns -1 and terminates
18         if (counter == 0)
19             return -1;
20 
21         // Values -1 or 0 could have been used as the initial
22         // value in this case, but also 33.4 because the patient
23         // temperature is always 33.5 degrees or higher. It could
24         // also be temperatures[0] as an initial value because
25         // if the counter is not zero, at least one array element
26         // value (the first element) was entered.
27         double max = Double.MIN_VALUE;
28 
29         for (int i = 0; i < counter; i++)
30             if (temperatures[i] > max)
31                 max = temperatures[i];
32 
33         return max;
34     }
35 
36     double findLowestTemperature(){
37         //If the array is empty, the method
38         // returns -1 and terminates
39         if (counter == 0)
40             return -1;
41 
42         // Values 41.6 could have been used as the initial
43         // value in this case because the patient
44         // temperature is always 41.5 degrees or lower. It could
45         // also be temperatures[0] as an initial value because
46         // if the counter is not zero, at least one array element
47         // value (the first element) was entered.
48         double min = Double.MAX_VALUE;
49 
50         for (int i = 0; i < counter; i++)
51             if (temperatures[i] < min)
52                 min = temperatures[i];
53 
54         return min;
55     }
56 
57     void print(){
58         for (int i = 0; i < counter; i++)
59             System.out.print(temperatures[i] + " ");
60 
61         if (counter == 0)
62             System.out.println("Array is empty");
63 
64         System.out.println();
65     }
66 
67 
68 }
 1 class TestPatientTemperatures {
 2 
 3     public static void main(String[] args) {
 4         PatientTemperatures pt = new PatientTemperatures();
 5 
 6         pt.enterTemperature(36.5);
 7         pt.enterTemperature(39.1);
 8         pt.enterTemperature(35.7);
 9 
10         pt.print();
11 
12         System.out.println("Highest temperature is: " + pt.findHighestTemperature());
13 
14         System.out.println("Lowest temperature is: " + pt.findLowestTemperature());
15     }
16 }

In the findHighestTemperature method, it first checks if the array is empty (if the counter is zero). If yes, it immediately returns -1 and the method stops.

If the array is not empty, an auxiliary variable max is used to “memorize” the current highest value of the array elements while iterating through the array.

The initial value of the max variable is set to the static constant Double.MIN_VALUE. This constant contains the smallest possible number representable by the double type. Why is this so? Because in the next steps, the max variable’s value will be compared with the array elements, which can only be equal to or greater than Double.MIN_VALUE, so the max variable will immediately take the value of the first array element it encounters.

In this specific case, another initial value for max could have been chosen, for example 0 or -1 or any number smaller than 33.5, since patient temperatures can only be higher than 33.5 degrees. Also, since the IF statement already checks that the counter is greater than zero and the array is not empty, the initial value could have been set to the first element of the array, then starting the search from the second element.

After that, a FOR loop iterates over the array elements, and at each iteration, it checks whether the current element is greater than the max variable. If not, it moves to the next iteration. If yes, the current element becomes the new maximum, and the max variable is assigned this value. This process repeats, gradually finding larger and larger values and storing them in max. When the FOR loop ends, max holds the largest value from the array.

It’s important to note that the loop runs over the actually entered values, i.e., from 0 to the counter, not to length-1. If it ran to length-1, it would unnecessarily compare also the “free” spots in the array which have the value 0. In this case, this would not cause an error but would make the method take longer.

The findLowestTemperature method works almost identically, starting with the empty array check (counter zero) and introducing an auxiliary variable min that “memorizes” the current smallest value.

The difference is in the initial value of min, which is Double.MAX_VALUE, the largest possible number representable by a double. The initial value in this case could be any number larger than 41.5, since that is the highest possible patient temperature. As in the previous method, the initial value could also be set to the first element of the array, then start the search from the second element.

The FOR loop goes through the temperature array searching for elements smaller than the current min. If found, it becomes the new minimum (assigned to min). When the loop ends, min contains the smallest value from the array.

Again, the loop runs from 0 to the counter, not to length-1. If it went to length-1, it would compare free spots with value 0, which would cause an error here because 0 is smaller than all real entered temperatures and would be incorrectly returned as the minimum.

The previous example was relatively simple because it was known whether the array was empty and how many elements it contained — due to the use of a counter. Moreover, patient temperatures were within a limited range (33.5 to 41.5 degrees), so the initial value for the auxiliary variable could be taken outside the expected temperature range or as the first array element (knowing whether the array is empty).

On the other hand, how can you find the maximum (or minimum), and what initial value to assign to the auxiliary variable if:

  • It is unknown whether the array is empty or how many values are really entered (no counter, or the entire array capacity is used).
  • There is no defined expected range of element values or no “impossible” values. For example, an array of monthly profits where each profit can be any number: zero, positive or negative, from a few hundred to several million.
  • There is no initial element value that can be considered a “free” slot in the array and ignored when searching for max/min.

In these cases, the only option is to set the initial value of the auxiliary variable to the value of some element of the array (usually the first), or to the smallest/largest value for that data type (Integer.MIN_VALUE, Double.MIN_VALUE, Integer.MAX_VALUE, or Double.MAX_VALUE).

Example 5

Create a class MonthlyProfits2 which has:

  • An attribute profits which is an array of 12 real numbers. Each element represents the profit for a specific month (January, February, …, December). The array should be initialized immediately with capacity 12.
  • A method enterProfit that takes as parameters a real number representing profit and an integer representing the month number (1 - January, 2 - February, …, 12 - December). The method inserts the appropriate profit value for that month into the array.
  • A method print that prints profits for all months on the screen.
  • A method findMaxProfit that finds the highest monthly profit in the array and returns it.
  • A method findMinProfit that finds the lowest monthly profit in the array and returns it.

Create a class TestMonthlyProfits2 which in the main method creates an object of the class MonthlyProfits2, enters the profit for February as 122.33, March as 200.1, and May as 255.44, then prints all monthly profits on the screen, and finally prints the highest and lowest monthly profit.

 1 class MonthlyProfits2 {
 2 
 3     double[] profits = new double[12];
 4 
 5     void enterProfit(double newProfit, int month){
 6         profits[month -1] = newProfit;
 7     }
 8 
 9     void print(){
10         for(int i = 0; i < profits.length; i++)
11             System.out.println(profits[i]);
12     }
13 
14     double findMaxProfit(){
15         //You could also put max = Double.MIN_VALUE;
16         double max = profits[0];
17 
18         // The loop counter starts from 1 and not from 0
19         // because the first element of the profits
20         // array is already taken as the initial value
21         // for max.
22         for (int i = 1; i < profits.length; i++)
23             if (profits[i] > max)
24                 max = profits[i];
25 
26         return max;
27     }
28 
29     double findMinProfit(){
30         //You could also put min = Double.MAX_VALUE;
31         double min = profits[0];
32 
33         // The loop counter starts from 1 and not from 0
34         // because the first element of the profits
35         // array is already taken as the initial value
36         // for min.
37         for (int i = 1; i < profits.length; i++)
38             if (profits[i] < min)
39                 min = profits[i];
40 
41         return min;
42     }
43 }
 1 class TestMonthlyProfits2 {
 2 
 3     public static void main(String[] args) {
 4         MonthlyProfits2 mp = new MonthlyProfits2();
 5 
 6         mp.enterProfit(122.33, 2);
 7         mp.enterProfit(200.1, 3);
 8         mp.enterProfit(255.44, 5);
 9 
10         mp.print();
11 
12         System.out.println("Highest profit is: " + mp.findMaxProfit());
13 
14         System.out.println("Lowest profit is: " + mp.findMinProfit());
15     }
16 }

In the finMaxProfit method, the algorithm is almost identical to the previous patient temperature example, except that the initial value for the auxiliary variable max is taken as the first element of the array. Accordingly, the FOR loop counter starts from 1 to length-1 (not from 0) because the first element is already taken as the initial max value, so the search starts from the second element. Alternatively, Double.MIN_VALUE could be used as the initial max value, and the loop would run from 0 to length-1, in which case a FOR-EACH loop could be used instead of a regular FOR loop.

Similarly for the findMinProfit method, where alternatively the initial min value could be Double.MAX_VALUE and the FOR loop runs from 0 to length-1 (instead of starting from 1 as currently). In that alternative, a FOR-EACH loop could also be used.

Most common errors

Some of the most common errors related to algorithms for group operations that are not syntax errors, but affect the program’s functionality, are:

  • When summing the elements of an array, setting the initial value of the auxiliary variable to a value other than zero (the neutral value for summation):
1     void sum(){
2         double totalProfit = -1;
3     
4         for(int i = 0; i < profits.length; i++)
5             totalProfit = totalProfit + profits[i];
6     
7         System.out.println("Total profit is: " + totalProfit);
8     }

Instead of correctly:

1     void sum(){
2         double totalProfit = 0;
3     
4         for(int i = 0; i < profits.length; i++)
5             totalProfit = totalProfit + profits[i];
6     
7         System.out.println("Total profit is: " + totalProfit);
8     }
  • When multiplying array elements, setting the initial value of the auxiliary variable to something other than one (the neutral value for multiplication) and getting an incorrect result. If the initial value is set to zero, the result of the multiplication will always be zero:
1     double multiply(){
2         // The result of multiplication with zero is always zero
3         double totalCofficient = 0;
4     
5         for(int i = 0; i < counter; i++)
6             totalCofficient = totalCofficient * coefficients[i];
7     
8         return totalCofficient;
9     }

Instead of correctly:

1     double multiply(){
2         double totalCofficient = 1;
3     
4         for(int i = 0; i < counter; i++)
5             totalCofficient = totalCofficient * cofficients[i];
6     
7         return totalCofficient;
8     }
  • During summing, multiplying or calculating the average of array elements when using a counter for the array, using all elements of the array (from 0 to length - 1) instead of only the truly entered ones (from 0 to counter - 1). If the unentered values are zero, summing or averaging will give a correct result, but multiplication will always result in zero. If the unentered values are not zero, all three operations will be incorrect (unless the values are 1, in which case multiplication would still be correct):
1     double multiply(){
2         double totalCofficient = 1;
3     
4         for(int i = 0; i < coefficients.length; i++)
5             totalCofficient = totalCofficient * coefficients[i];
6     
7         return totalCofficient;
8     }

Instead of correctly:

1     double multiply(){
2         double totalCofficient = 1;
3     
4         for(int i = 0; i < counter; i++)
5             totalCofficient = totalCofficient * coefficients[i];
6     
7         return totalCofficient;
8     }
  • Defining the auxiliary variable as int instead of double when calculating the average value of array elements. The result will be an integer without a decimal part, losing the precision of the average value (even if only the sum variable is defined as int):
 1     void printAverageAll(){
 2         int sum  = 0.0;
 3     
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         if (counter == 0)
 8             System.out.println("Array is empty");
 9         else {
10             double averageAll = sum / counter;
11             System.out.println("Average grade for all students is: " + averageAll);
12         }
13     }

Instead of correctly:

 1     void printAverageAll(){
 2         double sum  = 0.0;
 3     
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         if (counter == 0)
 8             System.out.println("Array is empty");
 9         else {
10             double averageAll = sum / counter;
11             System.out.println("Average grade for all students is: " + averageAll);
12         }
13     }
  • Dividing by the array length instead of the element counter when calculating the average value of array elements:
 1     void printAverageAll(){
 2         double sum  = 0.0;
 3 
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         if (counter == 0)
 8             System.out.println("Array is empty");
 9         else {
10             double averageAll = sum / grades.length;
11             System.out.println("Average grade for all students is: " + averageAll);
12         }
13     }

Instead of correctly:

 1     void printAverageAll(){
 2         double sum  = 0.0;
 3 
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         if (counter == 0)
 8             System.out.println("Array is empty");
 9         else {
10             double averageAll = sum / counter;
11             System.out.println("Average grade for all students is: " + averageAll);
12         }
13     }
  • Attempting to calculate the average of array elements when the counter is zero (the array is empty). This will lead to division by zero, and Java will report an error:
 1     void printAverageAll(){
 2         double sum  = 0.0;
 3     
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         // It could happen that the array is empty,
 8         // i.e. counter is 0. Then the following line
 9         // causes an error because it divides by zero.
10         double averageAll = sum / counter;
11     
12         System.out.println("Average grade for all students is: " + averageAll);
13     }

Instead of correctly (always check that brojac is not zero, and if it is, don’t divide):

 1     void printAverageAll(){
 2         double sum  = 0.0;
 3 
 4         for(int i = 0; i < counter; i++)
 5             sum = sum + grades[i];
 6     
 7         if (counter == 0)
 8             System.out.println("Array is empty");
 9         else {
10             double averageAll = sum / counter;
11             System.out.println("Average grade for all students is: " + averageAll);
12         }
13     }
  • Choosing an incorrect initial value for the auxiliary variable when finding the maximum or minimum. In the following example, all profits might be negative, and the initial value 0 would wrongly remain the maximum:
1     double findMaxProfit(){
2         double max = 0;
3     
4         for (int i = 0; i < profits.length; i++)
5             if (profits[i] > max)
6                 max = profits[i];
7     
8         return max;
9     }

Instead of correctly:

1     double findMaxProfit(){
2         double max = Double.MIN_VALUE;
3     
4         for (int i = 0; i < profits.length; i++)
5             if (profits[i] > max)
6                 max = profits[i];
7     
8         return max;
9     }

Or also correctly:

1     double findMaxProfit(){
2         double max = profits[0];
3     
4         for (int i = 1; i < profits.length; i++)
5             if (profits[i] > max)
6                 max = profits[i];
7     
8         return max;
9     }
  • When searching for the maximum or minimum of array elements in which a counter is used, using all elements of the array (from 0 to length - 1) instead of only the truly entered ones (from 0 to counter - 1). This can lead to incorrect results for max or min:
1     double findLowestTemperature(){
2         double min = Double.MAX_VALUE;
3     
4         for (int i = 0; i < temperatures.length; i++)
5             if (temperatures[i] < min)
6                 min = temperatures[i];
7     
8         return min;
9     }

Instead of correctly:

1     double findLowestTemperature(){
2         double min = Double.MAX_VALUE;
3     
4         for (int i = 0; i < counter; i++)
5             if (temperatures[i] < min)
6                 min = temperatures[i];
7     
8         return min;
9     }