November 6, 2026•5 min read

Java Operators: the Average That Came Out a Whole Number

Three scores, one division, and the average prints as 82. Both operands are int, so the fraction is cut off, and the obvious cast prints 82.0 without fixing anything.

Read in Indonesian

You add three test scores, divide by three, and print the result. The program prints 82. The number that should have come out was 82.33. Nothing raised an error and nothing warned you. The compiler accepted every line, and 82 is a believable score, which is exactly why it went unnoticed.

This article uses one small file. You will compile it, run it, look at the wrong number, change one thing, and run it again.

Key takeaways

  • int / int is integer division: the fraction is cut off, not rounded, so 247 / 3 is 82.
  • % returns what the division dropped: 247 % 3 is 1.
  • Casting the result ((double) (sum / count)) prints 82.0, because the division already happened in int.
  • Cast one operand ((double) sum / count) to divide in floating point and get 82.33333333333333.
  • A double cannot hold every decimal, since 0.1 + 0.2 is 0.30000000000000004, which is why money uses BigDecimal.
  • A test input that divides evenly, like 246 by 3, hides the bug in both versions.

The program that prints 82

Save this as Average.java. It holds three scores, adds them in a loop, and divides the sum by the length of the array.

JAVA
// Average.java
public class Average {
    public static void main(String[] args) {
        int[] scores = {80, 75, 92};
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        int average = sum / scores.length;
        System.out.println("sum: " + sum);
        System.out.println("average: " + average);
    }
}

Compile it and run it with two commands:

CONSOLE
javac Average.java
java Average

You should see this:

TEXT
sum: 247
average: 82

The sum is right, because 80 + 75 + 92 is 247. The average is not, because 247 / 3 is 82.33. The line int average = sum / scores.length; reads like the textbook formula, so a reviewer sees a sum divided by a count and moves on. The output is a whole number in a plausible range. Nothing about 82 looks broken.

What / does when both sides are int

The JVM decides the type of a division from its two operands. Here sum is an int and scores.length is an int, so / performs integer division and the result is an int. An int has no room for a fraction, so the fraction is dropped.

Dropped is not the same as rounded. It is cut off. 247 / 3 is 82, and 5 / 2 is 2, where rounding would have given you 3. The program never sees the .33 at all.

The % operator hands you the part that was dropped. 247 % 3 is 1: three goes into 247 eighty-two times, and one is left over. Put the pair together and nothing is lost, since 82 * 3 + 1 is 247.

Cast before the division, not after

The obvious repair is to ask for a double. Change the line to this:

double average = (double) (sum / scores.length);

It compiles without a warning and prints 82.0. That looks like a double, and a double looks precise, but it is not the average. The parentheses make the division run first, in int, and the result is 82. The cast then widens 82 to 82.0. The damage was done before the cast got a turn.

The cast has to sit on an operand: (double) sum / scores.length. A cast binds tighter than /, so sum becomes a double first. With one double on the left, Java widens the other operand to match and divides in floating point. The result is 82.33333333333333.

Here is the fixed file. It changes the type of average, moves the cast onto sum, and adds one line that prints the remainder explained above.

JAVA
// Average.java
public class Average {
    public static void main(String[] args) {
        int[] scores = {80, 75, 92};
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        double average = (double) sum / scores.length;
        System.out.println("sum: " + sum);
        System.out.println("average: " + average);
        System.out.println("remainder: " + sum % scores.length);
    }
}

Run the same two commands:

TEXT
sum: 247
average: 82.33333333333333
remainder: 1

Precedence and the rest of the operators

Multiplication, division and remainder bind tighter than addition and subtraction. So 1 + 2 * 3 is 7, while (1 + 2) * 3 is 9. Parentheses change which operation runs first. The cast bug is the same kind of mistake: the order Java evaluates things in decides the answer.

Integer division shows up outside averages too. 10 / 3 is 3. Make one operand a double and 10.0 / 3 is 3.3333333333333335. One .0 on one side turns a whole number into a long fraction.

Look at both long results again. 82.33333333333333 and 3.3333333333333335 do not end the way you would write them on paper. That leads to the one thing this article does not settle.

What this does not cover

A double cannot hold every decimal exactly. It stores binary fractions, and a value like 0.1 has no exact binary form. Add two of them and you can see the gap: 0.1 + 0.2 is 0.30000000000000004.

For money, that gap matters, and Java has BigDecimal for it. We will not use it here. An average of scores is not money. The error sits far past any digit a reader of a score would care about, so double is the right tool for this program.

Before the next article

Change one score so the three add up to 246: use 80, 75 and 91. Run the starter version, then the fixed version. This is what I measured. The truncating version prints 82, and the cast version prints 82.0. They agree, and neither answer looks wrong, because 246 divides by 3 exactly.

A data set that divides evenly hides the bug. Your task is to explain, in your own words, why the bug comes back the moment the sum is not divisible by the count.

If a result looks right on one input, which input would make it wrong?

Get better at shipping code.

Join the other developers getting tech updates, tips, and relaxed tutorials in their inbox every week.

Stay in the loop

Tech updates, coding tips, and relaxed insights straight to your inbox every week.

No spam. Unsubscribe anytime.

Read next

See all

For developers who learn by struggling

© 2026 Inva.dev.