Home › Guides › Java
Java9 min readCode verified

Math, Rounding and Casting: Why 7 / 2 Is 3

Java will tell you that 7 divided by 2 is 3, that (int) 7.9 is 7, and that Math.round(-2.5) is -2. None of those is a bug. Each comes from one small rule, and once you have the rules, arithmetic stops surprising you. Every listing here was compiled and run on OpenJDK 21.

Sharing a pizza#

Seven slices of pizza, two friends. Each friend gets 3 whole slices, and 1 slice is left over. Nobody cuts the last slice in half: whole slices only.

That is integer division, and it is exactly what Java does when both numbers are whole numbers. 7 / 2 is how many whole slices each person gets. 7 % 2, read as “7 mod 2”, is the leftover. The % sign is called the remainder operator.

public class Pizza {
    public static void main(String[] args) {
        System.out.println(7 / 2);
        System.out.println(7 % 2);
        System.out.println(7 / 2.0);
        System.out.println(7.0 / 2);
        System.out.println(-7 / 2 + " " + (-7 % 2));
    }
}
3
1
3.5
3.5
-3 -1

Change either number to a decimal, 2.0 or 7.0, and you are allowed to cut the last slice: the answer is 3.5. The rule is simple. If both sides of / are whole-number types, the fraction is thrown away. If either side is a decimal type, it is kept.

The last line shows what happens with negatives. Java throws away the fraction by moving towards zero, so -7 / 2 is -3, not -4, and the remainder takes the sign of the left-hand number: -1.

Promotion: the smaller type moves up#

When two different types meet in one expression, Java does not guess. It converts the smaller type up to the larger one, which is called promotion or widening. Nothing is lost going up, so Java does it without being asked. That automatic kind is an implicit conversion.

The order, smallest to largest, is: byte, short, int, long, float, double. A char joins the line at int.

public class Promote {
    public static void main(String[] args) {
        int apples = 3;
        double half = 0.5;
        double d = 5;
        char letter = 'A';
        System.out.println(apples + half);
        System.out.println(d);
        System.out.println(letter + 1);
        System.out.println((char) (letter + 1));
    }
}
3.5
5.0
66
B

apples + half is an int plus a double, so the int is promoted and the answer is a double. double d = 5; quietly stores 5.0.

The char lines surprise people. Underneath, a char is a number: 'A' is 65. Add 1 and you get the int 66, not the letter B. To get the letter, you have to convert back, which is the next section.

Casting: converting on purpose#

Going down, from a bigger type to a smaller one, can lose information. Java will not do it silently. You have to write a cast, which is the target type in brackets in front of the value: (int) 7.9. That is you saying “I know something might be lost; do it anyway.”

public class Casts {
    public static void main(String[] args) {
        System.out.println((int) 7.9);
        System.out.println((int) -7.9);
        System.out.println((double) 7 / 2);
        System.out.println((double) (7 / 2));
    }
}
7
-7
3.5
3.0

Three things to notice.

  • A cast chops, it never rounds. (int) 7.9 is 7. Casting just drops everything after the decimal point.
  • Chopping moves towards zero. (int) -7.9 is -7, not -8.
  • Where the cast sits changes the answer. (double) 7 / 2 converts 7 first, so the division keeps its fraction: 3.5. (double) (7 / 2) does the whole-number division first, gets 3, and only then converts it: 3.0. The fraction was already gone.

When you forget the cast#

Try to store a decimal in an int without a cast, and javac stops you:

public class Lossy {
    public static void main(String[] args) {
        int n = 3.5;
        System.out.println(n);
    }
}
Lossy.java:3: error: incompatible types: possible lossy conversion from double to int
        int n = 3.5;
                ^
1 error

“Lossy” means information would be lost: the .5. Going the other way, double d = 5;, needs no cast because nothing is lost. The rule of thumb is up is automatic, down needs a cast.

The Math class#

Java keeps its maths tools in a class called Math. You never create a Math object. Every method in it is static, meaning it belongs to the class rather than to any object, so you call it on the class name: Math.sqrt(49). Math lives in java.lang, which every program imports automatically.

public class Mathy {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(49));
        System.out.println(Math.pow(2, 5));
        System.out.println(Math.abs(-8.5));
        System.out.println(Math.max(3, 9) + " " + Math.min(3, 9));
        System.out.println(Math.ceil(4.1) + " " + Math.floor(4.9));
        System.out.println(Math.round(4.5) + " " + Math.round(-4.5));
        System.out.println(Math.PI);
    }
}
7.0
32.0
8.5
9 3
5.0 4.0
5 -4
3.141592653589793
MethodGives youReturns
Math.sqrt(x)square rootdouble
Math.pow(a, b)a to the power bdouble
Math.abs(x)distance from zerosame type as x
Math.max(a, b), Math.min(a, b)the larger, the smallersame type as the arguments
Math.ceil(x), Math.floor(x)round up, round downdouble
Math.round(x)nearest whole numberlong for a double
Math.PI, Math.Econstants, not methodsdouble

Two details catch people. Math.pow returns a double even for 2 to the 5, so it prints 32.0. And Java has no power operator: 2 ^ 5 compiles, but ^ means something else entirely and gives 7.

Math.round rounds a half upwards, towards positive infinity, even for negatives. So Math.round(4.5) is 5 but Math.round(-4.5) is -4.

Rounding to two decimal places#

Math.round only ever gives you a whole number. To round money to cents, you move the decimal point, round, and move it back. Three steps:

public class Money {
    public static void main(String[] args) {
        double price = 12.3456;
        double step1 = price * 100.0;
        long   step2 = Math.round(step1);
        double step3 = step2 / 100.0;
        System.out.println(step1 + " -> " + step2 + " -> " + step3);
        System.out.println(Math.round(price * 100.0) / 100.0);
        System.out.println(Math.round(price * 100) / 100);
    }
}
1234.56 -> 1235 -> 12.35
12.35
12
  1. Multiply by 100.0. 12.3456 becomes about 1234.56. The two digits you want to keep are now in front of the decimal point.
  2. Round to a whole number. 1234.56 becomes 1235.
  3. Divide by 100.0. 1235 becomes 12.35.

The first println shows all three steps side by side, so you can watch the number move.

The last line is the trap. Math.round(...) hands back a whole number, and 100 is a whole number, so step 3 becomes integer division: 1235 / 100 is 12. The .0 on 100.0 is doing real work. For one decimal place use 10.0; for three, 1000.0.

Math.round hands back a long#

Because Math.round of a double returns a long, you cannot drop the answer straight into an int:

public class RoundLong {
    public static void main(String[] args) {
        int r = Math.round(2.7);
        System.out.println(r);
    }
}
RoundLong.java:3: error: incompatible types: possible lossy conversion from long to int
        int r = Math.round(2.7);
                          ^
1 error

A long can hold numbers far bigger than an int, so storing one in an int is a narrowing conversion, and narrowing needs a cast. Either store it in a long, or write int r = (int) Math.round(2.7);.

The order Java works things out#

Java follows the same order you learned in maths class, with a few extra operators slotted in.

First to lastOperators
1brackets ( )
2casts, unary minus, !, ++, --
3* / %, left to right
4+ -, left to right
5comparisons < > <= >=, then == !=
6&&, then ||
7assignment = += -= and friends, last of all
public class Order {
    public static void main(String[] args) {
        System.out.println(2 + 3 * 4 - 6 / 2);
        System.out.println((2 + 3) * (4 - 6) / 2);
        System.out.println(10 - 4 - 3);
        final double TAX_RATE = 0.07;
        System.out.println(100 * TAX_RATE);
    }
}
11
-5
3
7.000000000000001

Line one: 3 * 4 and 6 / 2 happen first, then 2 + 12 - 3 is 11. Line two forces a different order with brackets. Line three shows “left to right”: 10 - 4 - 3 is (10 - 4) - 3, which is 3, not 10 - (4 - 3), which would be 9.

The last line is a warning about decimals, not about order. 100 times 0.07 should be 7, but it prints 7.000000000000001. Most decimal fractions cannot be stored exactly in binary, so a tiny error like this is normal, and it is one more reason to round money before you print it.

Those lines also use final, which makes a constant: a variable that gets one value and can never be changed. Constants are named in capitals with underscores by convention. Try to change one and the compiler refuses:

public class Constant {
    public static void main(String[] args) {
        final int MAX_SEATS = 30;
        MAX_SEATS = 31;
    }
}
Constant.java:4: error: cannot assign a value to final variable MAX_SEATS
        MAX_SEATS = 31;
        ^
1 error
One sentence to carry into the exam

Whole number divided by whole number throws the fraction away, a cast chops rather than rounds, and Math.round hands back a long. To round to two places: times 100.0, round, divide by 100.0, and keep the .0.

Where these go wrong#

  • Dividing two ints and expecting a fraction. 7 / 2 is 3. Make one side a double.
  • Casting after the division. (double) (a / b) is too late. Cast before: (double) a / b.
  • Expecting a cast to round. (int) 2.99 is 2. Use Math.round to round.
  • Dividing the rounded value by 100 instead of 100.0. That is integer division, and the cents disappear.
  • Storing Math.round(x) in an int. It returns a long; cast it.
  • Using ^ for powers. 2 ^ 5 is 7. Use Math.pow(2, 5).
  • Printing letter + 1 and expecting a letter. char plus int is an int. Cast back with (char).
  • Forgetting that final means final. A constant cannot be reassigned, even once.

Test yourself in the free Kestrel Exams app

Topic-selectable practice — offline, no ads, no account.

Practice casting and Math →

Frequently asked questions#

Why does 7 / 2 equal 3 in Java?

Because both 7 and 2 are ints, and dividing one whole-number type by another is integer division: Java keeps the whole-number part and throws the fraction away. The leftover is available separately with the remainder operator, 7 % 2, which is 1. If either number is a double, as in 7 / 2.0, the answer keeps its fraction: 3.5.

Does casting a double to an int round it?

No. A cast chops off everything after the decimal point, moving towards zero. (int) 7.9 is 7 and (int) -7.9 is -7. To round to the nearest whole number, use Math.round, which returns 8 for 7.9.

How do I round a double to two decimal places in Java?

Multiply by 100.0, round with Math.round, then divide by 100.0: Math.round(price * 100.0) / 100.0. The .0 on the second 100.0 matters. Without it, a whole number is divided by a whole number, integer division happens, and the decimals disappear.

Why can't I store Math.round in an int?

Because Math.round(double) returns a long, and a long can hold values too big for an int. Storing it in an int is a narrowing conversion, which javac rejects with possible lossy conversion from long to int. Store it in a long, or cast: int r = (int) Math.round(x).

What is the difference between implicit and explicit conversion in Java?

An implicit conversion happens automatically because nothing can be lost, such as storing an int in a double. An explicit conversion is a cast you write yourself, such as (int) 3.9, and it is required whenever information might be lost by going from a larger type to a smaller one.

What is the order of operations in Java?

Brackets first, then casts and unary operators, then * / and % from left to right, then + and - from left to right, then comparisons, then && and ||, and assignment last of all. So 2 + 3 * 4 - 6 / 2 is 11.

Suggest a change

Something here not clear? A topic you wish we covered? Tell us. We read every message, and a request is the fastest way to get a guide written — several of these exist because somebody asked.