Topic 24 of 119 3. Operators in Java Interactive Tutorial

Java Arithmetic: Mathematical Operators With Program Examples

13 mins read Last updated: 22 Aug 2026 19,152 views

Direct Answer & Core Concept

Java has five binary arithmetic operators: addition `+`, subtraction `-`, multiplication `*`, division `/` and remainder `%`. The behaviour depends entirely on the type of the operands, not on what the numbers look like. With two `int` values, division discards the fractional part, so `15 / 4` is `3`, and dividing an integer by zero throws `ArithmeticException: / by zero`. With `double` values the same division gives `3.75`, dividing by zero gives `Infinity` or `NaN` instead of throwing, and `0.1 + 0.2` is not exactly `0.3` because `double` stores values in binary. Java also widens the narrow types before computing, so a `byte` or a `char` in an expression is promoted to `int` and the whole result is an `int`, which is why `'A' + 'A'` is 130 rather than text. The remainder operator takes the sign of the dividend, so `-7 % 3` is `-1` while `7 % -3` is `1`. Finally, `+` is overloaded: if either operand is a `String` the operation becomes concatenation and the numeric result is never computed, so `"Score: " + 10 + 20` prints `Score: 1020`.

Detailed Explanation & Mechanics

1. The Five Binary Arithmetic Operators

Java has five arithmetic operators that take two operands, plus a family of unary ones covered in the unary operators topic. For beginners the five binary ones are the whole story.

OperatorName15 op 4Notes
+Addition19Doubles as concatenation if either side is a String
-Subtraction11Also the unary negation operator
*Multiplication60Written *, not x
/Division3Integer operands truncate towards zero
%Remainder (modulus)3Also called modulo. Sign follows the dividend

Two of these are common trip-ups for people arriving from other languages.

  • Multiplication is *, not x, because x is a perfectly legal variable name in Java.
  • The remainder operator is %, and it works on double as well as int, which surprises people who expect modulo to be integer-only.

2. Integer Division Silently Throws Away the Remainder

This is the single most important thing on the page. If **both** operands are integers, / performs integer division and throws the fractional part away. It does not round, and it does not warn you.

Main.java
Run Online
int dividend = 15;
int divisor = 4;
15 / 4 as integers = 3

The truncation happens because integer division is defined as "how many whole times does the divisor fit into the dividend", and 4 fits into 15 three whole times with 3 left over. That leftover is exactly what % gives you.

Main.java
Run Online
int dividend = 15;
int divisor = 4;
int quotient = dividend / divisor;
// 3
int remainder = dividend % divisor;
// 3
System.out.println(quotient + " remainder " + remainder);
// 3 remainder 3
// together they reconstruct the original: 3 * 4 + 3 == 15
ExpressionResultWhy
15 / 43Both int, so the fraction is discarded
15.0 / 43.75One double promotes the whole expression
15 / 4.03.75It only takes one double operand
15 / 4.0f3.75A float is enough, though less precise
-15 / 4-3Truncates towards zero, not downwards
15 / 0throwsArithmeticException: / by zero
15.0 / 0.0InfinityFloating point division by zero is defined

The fix is almost always to make one operand a floating-point value, either by writing 15.0 / 4 or by declaring the variable as double. Casting only the result, as in (double) (15 / 4), does **not** help, because the integer division has already happened by the time the cast runs.

3. Division by Zero: Two Completely Different Behaviours

Dividing by zero is an error for integers and perfectly legal for floating point. This trips up almost everyone once.

Main.java
Run Online
public class DivideByZero {
    public static void main(String[] args) {
        try {
            int bad = 15 / 0;
            // throws here
            System.out.println(bad);
        } catch (ArithmeticException e) {
            System.out.println("15 / 0     -> " + e.getClass().getSimpleName() + ": " + e.getMessage());
        } System.out.println("10.0 / 0.0  -> " +(10.0 / 0.0));
        System.out.println("-10.0 / 0.0 -> " +(-10.0 / 0.0));
        System.out.println("0.0 / 0.0   -> " +(0.0 / 0.0));
    }
}

The real output:

Main.java
Run Online
15 / 0 -> ArithmeticException: / by zero 10.0 / 0.0 -> Infinity -10.0 / 0.0 -> -Infinity 0.0 / 0.0 -> NaN
  • Integer division by zero throws ArithmeticException because the answer has no mathematical meaning and there is no nearest value to return.
  • Floating point division by zero follows the IEEE 754 standard and produces a special value instead. x / 0.0 gives Infinity when x is positive and -Infinity when x is negative.
  • 0.0 / 0.0 is NaN, short for Not a Number, because the question has no answer at all.

There is one consequence of NaN that catches people out later, so it is worth knowing now.

Main.java
Run Online
double x = 0.0 / 0.0;
System.out.println(x == x);
// false!  NaN is not equal to itself
System.out.println(x != x);
// true, and also NaN

Comparing with == will never be true for NaN. The correct test is Double.isNaN(x).

4. The Remainder Operator and the Sign Rule

% gives the leftover after division, and its sign rule surprises people who learned modulo in mathematics.

**In Java the result takes the sign of the dividend**, the number on the left, not the divisor on the right.

Main.java
Run Online
dividend % divisor -7 % 3 = -1 dividend negative -> result negative 7 % -3 = 1 dividend positive -> result positive -7 % -3 = -1 dividend negative -> result negative 7 % 3 = 1 both positive -> result positive

This matches truncating integer division: -7 / 3 is -2, and -2 * 3 is -6, so the remainder must be -1 to bring the total back to -7. Mathematicians usually define modulo to follow the divisor instead, so 7 % -3 is 1 in Java but 4 in pure mathematics. This is a genuine difference between the two, not a Java bug.

Main.java
Run Online
System.out.println(7 / 3);
//  2
System.out.println(7 % 3);
//  1   and 2 * 3 + 1 == 7
System.out.println(-7 / 3);
// -2   truncated towards zero, not -3
System.out.println(-7 % 3);
// -1   so that -2 * 3 + -1 == -7

That second pair is worth memorising, because truncating towards zero is the opposite of what a maths textbook does. Note that % is not limited to integers; 5.5 % 2.0 is legal and gives 1.5.

5. Narrow Types Are Promoted to int Before Arithmetic

Java has eight primitive numeric types, but arithmetic on byte, short and char is always carried out in int. The result is an int, and it never quietly becomes a byte again.

Architecture Diagram
the promotion rule for binary arithmetic

   byte   ->  int      short  ->  int      char   ->  int
                                     |
                                     +--> everything below
                                     |
   int  ->  int      long  ->  long      float  ->  float      double -> double

   if either side is a double, the whole expression is a double
   otherwise if either side is a float, the whole expression is a float
   otherwise if either side is a long, the whole expression is a long
   otherwise everything is an int

Here is the whole ladder printed by one small program, using getClass() so nothing is guesswork.

Main.java
Run Online
public class Promotion {
    public static void main(String[] args) {
        byte b = 10;
        short s = 20;
        char c = 'A';
        int i = 30;
        long L = 40L;
        float f = 1.5f;
        double d = 2.5;
        show("byte + byte", b + b);
        show("short + byte", s + b);
        show("char + char", c + c);
        show("int + long", i + L);
        show("long + float", L + f);
        show("int + double", i + d);
        show("float + double", f + d);
    } static void show(String label, Object value) {
        System.out.printf("%-14s = %-8s  type %s%n", label, value, value.getClass().getSimpleName());
    }
}
Main.java
Run Online
byte + byte = 20 type Integer short + byte = 30 type Integer char + char = 130 type Integer int + long = 70 type Long long + float = 41.5 type Float int + double = 32.5 type Double float + double = 4.0 type Double
  • byte + byte gives an Integer, never a Byte. This is exactly why byte c = b + b; fails to compile and needs (byte) written for you, which is the implicit cast discussed in the assignment topic.
  • char promotes to int, so 'A' + 'A' is 130 and the character sum is a number, not text. To get a character back you must cast: (char) ('A' + 1) is 'B'.
  • long promotes to float, not the other way round, so a long + float gives a Float even though a long can hold far bigger numbers. This loses precision.
  • float + double is a Double, because a double is the widest type in the language and it wins.

6. Why 0.1 + 0.2 Is Not Exactly 0.3

If you have used JavaScript or Python you may already know this one, but it is worth seeing in Java because double is the default type for decimal literals.

Main.java
Run Online
public class Precision {
    public static void main(String[] args) {
        System.out.println("0.1 + 0.2 = " +(0.1 + 0.2));
        System.out.println("is it == 0.3 ? " +((0.1 + 0.2) == 0.3));
        System.out.println("0.1f + 0.2f = " +(0.1f + 0.2f));
    }
}
Main.java
Run Online
0.1 + 0.2 = 0.30000000000000004 is it == 0.3 ? false 0.1f + 0.2f = 0.3

The reason is that a double stores values in binary, and 0.1 has no exact binary representation, just as one third does not. The stored value is extremely close, and adding the two slightly-wrong approximations lands just above 0.3. Printing shows all seventeen digits, so the error is visible.

Two more precision facts worth knowing:

  • float has roughly 7 significant digits and double roughly 15 to 17, so float loses the error sooner. That is why 0.1f + 0.2f prints a tidy 0.3: the answer is wrong in the same direction, it just has too few digits left to show it.
  • A float cannot represent every int. (float) 16777217 prints 1.6777216E7, which is not the number you started with. The fix is to convert the other way, to double, which can hold every int exactly.

For money, never use double. Use BigDecimal, or store an amount of cents as a long.

Main.java
Run Online
import java.math.BigDecimal;
BigDecimal total = new BigDecimal("0.10").add(new BigDecimal("0.20"));
System.out.println(total);
// 0.30, exactly
System.out.println(total.compareTo(new BigDecimal("0.30")) == 0);
// true

Note the string constructor. Writing new BigDecimal(0.1) imports the same binary approximation error you were trying to escape.

7. Integer Overflow Is Silent Too

Arithmetic on int and long wraps around rather than throwing, so a calculation that grows too large quietly produces a wrong answer. The full treatment is in the assignment topic, but it belongs here too because it is arithmetic behaviour.

Main.java
Run Online
int big = 2000000000;
int doubled = big * 2;
// wraps to a negative number
System.out.println(doubled);
// -294967296

For money, byte counts, or anything read from a file, use a wider type or ask for a check.

Main.java
Run Online
int a = 2000000000;
int safe = Math.addExact(a, a);
// throws ArithmeticException on overflow

8. + Is Overloaded: Addition or Concatenation

The + operator does double duty. If **either** operand is a String, the operation becomes text concatenation and no numeric addition happens at all. The evaluation is left to right, which produces results that look like bugs.

Main.java
Run Online
"Score: " + 10 + 20 step 1: "Score: " + 10 -> "Score: 10"(a String is now involved) step 2: "Score: 10" + 20 -> "Score: 1020"(so 20 is appended, not added) 10 + 20 + " Score" step 1: 10 + 20 -> 30(both are numbers, so it adds) step 2: 30 + " Score" -> "30 Score"(now it concatenates)
Main.java
Run Online
System.out.println("Score: " + 10 + 20);
// Score: 1020
System.out.println(10 + 20 + " Score");
// 30 Score
System.out.println(1 + 2 + "x");
// 3x
System.out.println("x" + 1 + 2);
// x12

To get the arithmetic answer you have to force it before the String appears, either with parentheses or by converting the number first.

Main.java
Run Online
System.out.println("Score: " +(10 + 20));
// Score: 30
System.out.println("Score: " + 10 +(20 + 0));
// Score: 30
System.out.println("Score: " + String.valueOf(10 + 20));
// Score: 30

The parentheses are the cleanest option and the one to reach for by default.

9. Compound Arithmetic Operators

The compound forms from the assignment topic, +=, -=, *=, /= and %=, work with arithmetic and save repeating the variable. They are not separate arithmetic operators, just shorthands.

Main.java
Run Online
int n = 20;
n += 5;
// 25
n -= 3;
// 22
n *= 2;
// 44
n /= 4;
// 11
n %= 4;
//  3
System.out.println(n);
// 3

Because the division is still integer division, n /= 4 truncates just as / would.

10. Operator Precedence and Parentheses

Multiplication and remainder bind more tightly than addition and subtraction, and all of them bind more tightly than assignment. Parentheses override all of it, so use them whenever the intent is not obvious.

Main.java
Run Online
System.out.println(2 + 3 * 4);
// 14, not 20
System.out.println((2 + 3) * 4);
// 20
System.out.println(10 - 4 - 3);
// 3, subtraction is left to right
System.out.println(10 -(4 - 3));
// 9

The full table, including the comparison and logical operators, is in the operator precedence topic.

11. Common Arithmetic Mistakes

What You WroteWhat You GetFix
15 / 4 expecting 3.753Write 15.0 / 4
(double)(15 / 4)3.0Cast an operand, not the result: (double)15 / 4
a / b where b may be 0ArithmeticExceptionCheck b != 0 first
Comparing with == after dividing by 0.0Always false for NaNUse Double.isNaN(x)
Expecting the sign of the divisor in %Sign follows the dividendTake the sign yourself, or use Math.floorMod
"Total: " + 5 + 5Total: 55Parenthesise: "Total: " + (5 + 5)
0.1 + 0.2 == 0.3falseCompare with a tolerance, or use BigDecimal
Using double for moneyDrifting totalsUse BigDecimal or a long of cents
byte c = b + b;Compile errorCast: byte c = (byte)(b + b);
'A' + 1 expecting 'B'66Cast: (char)('A' + 1)
Large int arithmeticSilent overflowUse long or Math.addExact
2 + 3 * 4 expecting 2014Parenthesise: (2 + 3) * 4

12. Arithmetic Cheat Sheet

QuestionAnswer
Binary arithmetic operators+ - * / %
15 / 4 with ints3, truncated towards zero
15.0 / 43.75
-7 / 3 with ints-2, not -3
Integer division by zeroThrows ArithmeticException
x / 0.0 with doublesInfinity, -Infinity, or NaN for 0.0/0.0
Is NaN equal to itselfNo, use Double.isNaN
Sign of the modulus resultFollows the dividend
Type of byte + byteint, so it cannot be assigned to a byte
Type of char + charint, so 'A' + 'A' is 130
Widest type winsdouble beats float, long, int and the small types
0.1 + 0.20.30000000000000004
Money typeBigDecimal, never double
Integer overflowSilent wrap, never an exception
Does + ever concatenateYes, if either operand is a String
Precedence* and % before + and -

Arithmetic in Java looks simple and then surprises you twice: once because / quietly discards the remainder when both sides are integers, and once because + quietly becomes text as soon as a String is involved. Everything else on this page is detail hanging off those two rules, along with the promotion of small types to int and the fact that neither division by zero nor overflow always tells you loudly that something went wrong.

Runnable Code Example: Java Arithmetic

Java 17+
Main.java
Run Online
public class ArithmeticDemo {
    public static void main(String[] args) {
        // ---------- the five binary arithmetic operators ----------
        int a = 15, b = 4;
        System.out.println(a + " + " + b + " = " +(a + b));
        // 19
        System.out.println(a + " - " + b + " = " +(a - b));
        // 11
        System.out.println(a + " * " + b + " = " +(a * b));
        // 60
        System.out.println(a + " / " + b + " = " +(a / b));
        //  3, NOT 3.75
        System.out.println(a + " % " + b + " = " +(a % b));
        //  3
        // ---------- one literal changes everything ----------
        // with an int operand, / is integer division and truncates
        System.out.println("15 / 4  = " +(15 / 4));
        // with a double operand, / is real division
        System.out.println("15.0 / 4 = " +(15.0 / 4));
        // ---------- integer division by zero throws ----------
        try {
            int oops = 15 / 0;
            System.out.println("never reached: " + oops);
        } catch (ArithmeticException e) {
            System.out.println("15 / 0 throws: " + e.getMessage());
        } // ---------- floating point division by zero does not ----------
        System.out.println("10.0 / 0.0  = " +(10.0 / 0.0));
        System.out.println("0.0 / 0.0   = " +(0.0 / 0.0));
        // ---------- the remainder takes the sign of the dividend ----------
        System.out.println("-7 % 3  = " +(-7 % 3));
        // -1
        System.out.println("7 % -3  = " +(7 % -3));
        //  1
        // ---------- + becomes concatenation if any operand is a String ----------
        System.out.println("10 + 20 + \" Score\" = " +(10 + 20 + " Score"));
        System.out.println("\"Score: \" + 10 + 20 = " +("Score: " + 10 + 20));
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

What is integer division in Java and why does it matter?

When both operands of / are integer types, the result is an integer and the fractional part is discarded, so 15 / 4 is 3. It does not round. To get 3.75 you need a floating-point operand, such as 15.0 / 4. Casting the result afterwards, as in (double)(15 / 4), is too late because the truncation has already happened and you get 3.0.
Q2

What happens when you divide by zero in Java?

It depends on the type. Integer division by zero throws ArithmeticException with the message "/ by zero". Floating-point division by zero follows IEEE 754 and returns Infinity for a positive numerator, -Infinity for a negative one, and NaN when both are zero. Nothing is thrown in the floating-point case.
Q3

Why is x == x false when x is NaN?

Because IEEE 754 defines NaN as unequal to everything, including itself, so that a NaN result can never be mistaken for a real value. == is therefore useless for detecting it. Use Double.isNaN(x), or compare with != which is true for NaN.
Q4

What is the sign rule for the remainder operator in Java?

The result of % takes the sign of the dividend, the left operand. So -7 % 3 is -1 and 7 % -3 is 1. This follows from integer division truncating towards zero: -7 / 3 is -2, and -2 * 3 is -6, so the remainder must be -1. If you want the sign of the divisor instead, which is what mathematical modulo usually does, use Math.floorMod.
Q5

Why does byte + byte not produce a byte?

Java promotes byte, short and char to int before any binary arithmetic, and the result of the operation is an int. So byte c = b + b; is rejected as a lossy conversion. You must write byte c = (byte)(b + b); and the cast can itself truncate. The same promotion is why 'A' + 'A' is the number 130, and you need (char)('A' + 1) to get a character.
Q6

What is the promotion order for mixed numeric types?

If either operand is a double the result is a double, otherwise if either is a float the result is a float, otherwise if either is a long the result is a long, and otherwise the result is an int. This means long + float is a float, which loses precision even though a long holds a much wider range, and it is a common source of surprise.
Q7

Why is 0.1 + 0.2 not equal to 0.3 in Java?

A double stores values in binary, and 0.1 has no exact binary representation, so both operands are stored as extremely close approximations. Adding them lands just above 0.3, giving 0.30000000000000004. A float has only about 7 significant digits, so 0.1f + 0.2f prints a tidy 0.3 while being just as wrong. For money use BigDecimal built from strings, never from doubles.
Q8

Does Java throw an exception on integer overflow?

No. Arithmetic on int and long wraps silently, so 2000000000 * 2 gives -294967296 with no warning. Use long when the range might be exceeded, or Math.addExact and Math.multiplyExact when you want an ArithmeticException instead of a wrong number.
Q9

How does the + operator decide between addition and concatenation?

If either operand is a String the operation becomes concatenation and the other operand is converted to text, so no numeric addition occurs. Evaluation is left to right, which is why "Score: " + 10 + 20 gives "Score: 1020" while 10 + 20 + " Score" gives "30 Score". Parenthesise the numeric part, as in "Score: " + (10 + 20), to get "Score: 30".
Q10

What is the precedence of the arithmetic operators?

Multiplication * and remainder % bind more tightly than addition + and subtraction -, and all of them bind more tightly than assignment. So 2 + 3 * 4 is 14, not 20. Operators of equal precedence are evaluated left to right, so 10 - 4 - 3 is 3. Parentheses override everything.
Q11

Is modulo an integer-only operator in Java?

No. The remainder operator works on double as well, so 5.5 % 2.0 is 1.5. This is different from C and C++, where % is restricted to integers, and it is occasionally useful.
Q12

How should you represent money in Java?

Never with double, because binary representation error accumulates. Use java.math.BigDecimal and build it from a String, as in new BigDecimal("0.10"), so you never import the binary approximation. Compare BigDecimal values with compareTo rather than equals, since equals also checks scale, so new BigDecimal("1.0").equals(new BigDecimal("1.00")) is false even though the numbers match.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Make the numeric type of your variables deliberate rather than defaulting everything to int, because the type decides whether division truncates, whether it can overflow, and how precise it is. Wherever a division might not divide evenly, use a double on at least one operand and remember that casting the result afterwards is too late, since the truncation has already happened. Never represent money in double or float: use BigDecimal built from a String with new BigDecimal("0.10") so you do not import the binary approximation error, and compare values with compareTo rather than equals, because equals also compares scale and will report 1.0 and 1.00 as different. Guard every integer division against a zero divisor, since that throws while floating point silently gives Infinity or NaN, and remember that NaN fails every equality test so use Double.isNaN. Add parentheses wherever the precedence of * and % is not obvious, because a missing bracket is a silent logic error rather than a compile error. Prefer Math.addExact and Math.multiplyExact over plain arithmetic when values come from outside your program, so an overflow becomes an ArithmeticException rather than a wrong number that surfaces much later.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.