Sum and average over an array
The accumulator pattern: declare a running total before the loop, add each element to it inside the loop, return the total (or divide by length to get the average) after the loop. This is the first composite loop pattern students see, and it underlies count, max, min, and most other reductions.
public static int sum(final int[] xs) {
int total = 0;
for (int v : xs) {
total += v;
}
return total;
}
public static double average(final int[] xs) {
return (double) sum(xs) / xs.length;
}
Three commitments are visible in this shape:
1. The accumulator starts at the identity element. For sum, the identity is 0: adding it changes nothing. For product, the identity is 1. For min, the identity is Integer.MAX_VALUE. Choosing the right starting value matters, and the best-so-far pattern for min and max revisits this. 2. The loop body's only effect is to update the accumulator. No System.out.println, no array writes, no early return. The body is one operation per slot. 3. The accumulator is the answer. The method returns it directly. No second pass is needed.
The enhanced-for is the natural choice here (the body uses only the value, never the index). The traditional for is identical in behavior: pick the form that reads cleanly.
Average is not sum / length with integer arithmetic
return sum(xs) / xs.length; // BUG: integer division
If sum returns int and xs.length is int, the / is integer division, which truncates toward zero. For an array of three values {1, 1, 2}, the sum is 4, the length is 3, and 4 / 3 is 1, not 1.333…. The fix is to promote at least one operand to double:
return (double) sum(xs) / xs.length; // promote the dividend; quotient is 1.333…
return sum(xs) / (double) xs.length; // promote the divisor; same result
return (sum(xs) * 1.0) / xs.length; // multiplication promotes; works but ugly
The cast on the dividend is the conventional form.
Overflow on int accumulators
For a large array of int values, the sum can exceed Integer.MAX_VALUE (2 147 483 647) and wrap around silently to a negative number. This rarely matters for CSCD 210 lab data (small arrays of small values) but is a real production concern. The fix is to declare the accumulator as long:
long total = 0L;
for (int v : xs) total += v;
return total;
For double arrays the analogous concern is loss of precision when summing many small values together; the textbook discusses this only briefly (BJP.p269) and CSCD 210 does not assess it.
In other languages
- Python:
sum(xs)is a built-in;statistics.mean(xs)returns the average. Both handle integer division automatically because Python's/is always floating-point. - C: identical accumulator pattern; the same overflow risk on
intaccumulators.long longis the C equivalent of Java'slong. - Java streams:
IntStream.of(xs).sum()andIntStream.of(xs).average()exist; out of scope for CSCD 210.