1. Introduction
Arithmetic operators play a fundamental role in programming. They enable developers to perform mathematical calculations in their code. Java provides you with a set of operators to perform your usual mathematical operations: addition, subtraction, multiplication, division, and modulo. In this article, you’ll discover how each of these operators works, as well as the precedence and associativity rules that govern them. Although most arithmetic operators are binary, we will see that there are also unary arithmetic operators in Java.
2. Summary of Arithmetic Operators
The table below summarizes the arithmetic operators and their meanings.
Operator | Meaning | Example |
---|---|---|
a + b | Mathematical addition | i = 1 + 2 ;//i = 3 |
a – b | Mathematical subtraction | i = 5 – 1;//i = 4 |
a * b | Mathematical multiplication | i = 2 * 3; //i = 6 |
a / b | Mathematical division. Make sure b != 0 | i = 4 / 2; // i=2 |
a % b | Returns the remainder of the division of a by b. Make sure b != 0 | i = 10 % 5; //i=0 |
+ a | Positive a | i = +1; //i=1 |
– a | Negative a | i = -1; //i=-1 |
a++ | Use the current value of a, then increment it just after | i=0; j = i++;//j=0; i=1 |
a– | Use the current value of a, then decrement it just after | i=0; j = i–;//j=0; i=-1 |
++a | Increment the current value of a before using it | i=0; j = ++i;//j=1; i=1 |
–a | Decrement the current value of a before using it | i=0; j = –i;//j=-1; i=-1 |
a op= b | op can be any of the previous operator : +, -, *, /, and %. | i += j; //i = i + j; i -= j; //i = i – j; i *= j; //i = i * j; i /= j; //i = i / j; |
Before turning to the operators themselves, let’s take a look at a few important aspects of machine arithmetic.
3. Integer Arithmetic
Any arithmetic operation on integers always returns a value that is in the corresponding range. The only exception is division by 0 which throws an ArithmeticException. You must therefore be aware of this in your manipulations. Take the following example:
int tooBigInteger = Integer.MAX_VALUE + 1;
int tooSmallInteger = Integer.MIN_VALUE - 1;
System.out.println(tooBigInteger);
System.out.println(tooSmallInteger);
Running this program will produce the following output :
-2147483648
2147483647
As you can see, adding one to the biggest integer leads to the smallest integer. Meanwhile removing one to the smallest integer gives the biggest integer.
The result of any integer operation is reduced modulo the range of the result type.
long notTooBigLong = Integer.MAX_VALUE + 1L;
long notTooSmallInteger = Integer.MIN_VALUE - 1L;
System.out.println(notTooBigLong);
System.out.println(notTooSmallInteger);
Running this program will produce the following output :
2147483648
-2147483649
4. Floating-Point Arithmetic
When talking about operations on floating-point numbers, there are four terms to know: overflow, underflow, Infinity, and NaN.
4.1. Overflow
This is when the result of an operation is too big to fit in the given type (Float or Double). It can happen for example if you try to multiply two very large numbers.
double result = Double.MAX_VALUE * Double.MAX_VALUE;
System.out.println(result);//Prints: Infinity
4.2. Infinity
The notion of infinity represents a number that is too large to fit in a Double (or a Float). Infinity also occurs when you try to divide a floating-point number by zero.
double result = 1.0/0.0;
System.out.println(result);//Prints: Infinity
This notion is translated in Java by two constants in the Double (or Float) class. These constants are Double.POSITIVE_INFINITY(Float.POSITIVE_INFINITY) if the divisor is positive and Double.NEGATIVE_INFINITY(Float.NEGATIVE_INFINITY) if it is negative.
double positiveInfinity = Double.POSITIVE_INFINITY;
double negativeInfinity = Double.NEGATIVE_INFINITY;
double positiveDivisorInfinity = 1.0 / 0.0;
double negativeDivisorInfinity = -1.0 / 0.0;
System.out.println(positiveInfinity);//Prints: Infinity
System.out.println(negativeInfinity);//Prints: Infinity
System.out.println(positiveDivisorInfinity == positiveInfinity);//Prints: true
System.out.println(negativeDivisorInfinity == negativeInfinity);//Prints: true
4.3. Underflow
Underflow will happen when the result of an operation is too small to be represented as a double or float. This can happen in two situations :
- The result is between Double.MIN_VALUE(or Float.MIN_VALUE) and 0. Underflow will return positive zero 0.0 (or 0.0F).
- The result is between -Double.MIN_VALUE(or Float.MIN_VALUE) and 0. Underflow will return negative zero -0.0 (or -0.0F).
Positive zero is equal to negative zero.
double positiveZero = Double.MIN_VALUE / 2;
double negativeZero = -Double.MIN_VALUE / 2;
System.out.println(positiveZero);//Prints: 0.0
System.out.println(negativeZero);//Prints: -0.0
System.out.println(positiveZero == negativeZero);//Prints: true
4.4. NaN
NaN means Not A Number. When the operation has no mathematics result, you receive a NaN. For example, calculating a square root of a negative number or dividing zero by zero.
Any operation involving a NaN produces a NaN.
double result = 0.0/0.0;
System.out.println(result);//Prints: NaN
System.out.println(result + 1);//Prints: NaN
5. Binary Operators
5.1. Multiplication *
This operator performs the simple mathematical multiplication of two numbers.
int result = 3 * 2;
System.out.println(result);//Prints 6
5.2. Division /
The division operator is overloaded in Java. This means that when the two operands are integer values, it is the quotient of the division that is returned. If at least one of the operands is a floating-point number, decimal division is applied.
int i = 4 / 2;// result : 2 --Integer division
int j = 1 / 2;// result : 0 --Integer division
double d1 = 12 / 8;// result : 1 --Integer division
double d2 = 12.0 / 8;// result : 1.5 --Floating-point division
When performing an integer division, if the divisor is zero, an ArithmeticException is thrown.
int i = 4 / 0;// throws ArithmeticException at runtime
5.3. Modulo %
In mathematics, the modulus of a by b is the remainder of the Euclidean division of a by b.
a % b is then defined by the following formula :
a % b = a – (b * q) where q = a / b
In Java, the modulo operator applies not only the integers but also to floating-point numbers.
int r1 = 10 % 2; // result : 0
int r2 = 12 % 5; // result : 2
int r3 = 12 % -5; // result : 2
int r4 = -12 % 5; // result : -2
int r5 = 1 % 0.5; // result : 0
Because this operator involves the division operator, if the divisor is 0, an ArithmeticException is thrown. If the dividend is a floating-point number, NaN is returned.
int r1 = 10 % 0; // throws ArithmeticExcecption at runtime
int r1 = 10.0 % 0; // result: NaN
5.4. Addition and Subtraction +,-
These two operators have the lowest precedence of arithmetic operators. Below are some examples of how to use them.
int i1 = 1 + 2;//result: 3
int i2 = 5 - 10;//result: -5
5.5. Arithmetic Compound Assignment +=, -=, *=, /=, %=
These operators are shortcuts to standard arithmetic operators in certain specific situations. How they work is summarized in the table below:
Operator | Meaning |
---|---|
a += b | a = a + b |
a -= b | a = a – b |
a *= b | a = a * b |
a /= b | a = a / b |
a %= b | a = a % b |
Here is an example of how to use the +=:
int i = 1;
int j = 2;
i += j; //i = i + j = 1 + 2 = 3
6. Unary Operators
Unary arithmetic operators have high precedence compared to binary operators.
6.1. Unary Operator +,-
The unary operator – negates the numeric value of its operand.
int value = - -20;
System.out.println(value);//Prints : 20
The unary operator + has no effect.
int value = + -20;
System.out.println(value);//Prints : -20
6.2. Increment and Decrement Operator: ++, —
These two operators increment or decrement the value of the variable to which they apply. When placed before the variable, they are called prefixes; and when they are placed after, they are called postfixes.
The table below summarizes how these operators work:
Operator | Meaning |
---|---|
i++ | Use the current value of i and then increment it after |
++i | Increment the current value of i before using it |
i– | Use the current value of i and then decrement it after |
–i | Decrement the current value of i before using it |
6.2.1. The Increment Operator ++
Prefix Increment ++i
int i = 1;
int j = ++i;//j = 2
int k = i; // k = 2
Postfix Increment i++
int i = 1;
int j = i++;//j = 1
int k = i; // k = 2
6.2.2. The Decrement Operator —
Prefix Decrement –i
int i = 1;
int j = --i;//j = -1
int k = i; // k = -1
Postfix Decrement i–
int i = 1;
int j = i--;//j = 1
int k = i; // k = -1
7. Numeric Promotion in Arithmetic Expressions
Numeric operators in Java only allow operands of a certain type. Numeric promotion will therefore make it possible to convert the operands into the data type authorized by the operator.
7.1. Unary Numeric Promotion
Unary numeric promotion is applied in the following expressions :
7.1.1. Operands of unary arithmetic operators + and –
When this operator is applied to an operand of a type smaller than int
, the operand is promoted to type int
.
short value = 30;
value = -value;//Compile-time error -value is promoted to the type int
value = (short) -value;//This is OK, explicit cast is needed
7.1.2. Array creation expression: the size must be of type int
The array operator [] needs the length to be of type int
.
short length = 10;
int[] arr = new int[length];//This is OK, length is promoted to the type int
7.1.3. Indexing array elements: the index must be of type int
Just like the array size, the index of an array must be of type int
.
short length = 10;
byte index = 0;
int[] arr = new int[length];
arr[index] = 4;//This is OK, index is promoted to the type int
7.2. Binary Numeric Promotion
Binary Numeric Promotion guarantees that each operand of a numeric operation is at least of type int
. If one of the operands is of a type wider than int
, both operands are converted to that type. Otherwise, both operands are converted to type int
.
Binary numeric promotion is applied to the following expressions:
7.2.1. Operands of arithmetic operators +, -, *, /, and %
short value = 5;
value = value + 1;//Compile-time error value + 1 is promoted to the type int
value = (short) (value + 1);//This is OK, explicit cast is needed
7.2.2. Operands of relational operators <, <=, >, >=, ==, and !=
short a = 5;
byte b = 10;
boolean test = a < b;//This is OK, a and b are promoted to the type int
8. Operator Precedence And Associativity
The table below shows the precedence rules for arithmetic operators in descending order. It’s the same order you learned in maths.
Operators | Precedence |
---|---|
Unary postfix operators | expression++ expression– |
Unary prefix operators | ++expression –expression +expression -expression |
Multiplicative | * / % |
Additive | + – |
The unary operators have right associativity and the binary operators have left associativity.
You can read more about Precedence And Associativity Rules here.
9. Conclusion
In this article, you studied the various arithmetic operators available in Java. You have also seen the precedence and associativity rules between these operators.
10. References
1) OCP Oracle Certified Professional Java SE 17 by Khalil A. Mughal and Vasily A. Strelnikov
2) Oracle Java Documentation
Pingback: Java Operators Decoded: Essential Tools for Crafting Robust Code