Arithmetic Operators
Simple Math
There are five simple arithmetic operators, most of which should be familiar to you.
Operator
Description
+
Addition operator.
-
Subtraction operator.
*
Multiplication operator.
/
Division operator.
%
Integer remainder operator.
The addition operator works exactly as you might expect it to. It computes the sum of two numbers.
int a = 1;
int b = 2;
int c = a + b; // sum of a and b is computed, stored in c
Subtraction is equally straightforward.
int a = 3;
int b = 2;
int c = a - b; // difference between a and b is computed, and stored in c
Multiplication, too, is as expected. No surprises here.
int a = 2;
int b = 3;
int c = a * b; // product of a and b is computed, stored in c
The division operator behaves a littler differently than you might expect, depending on the operands (or more specifically, their data types). If either operand is a floating-point number, then the division operator performs floating-point division.
double a = 3.0;
double b = 2.0;
double c = a / b; // 1.5 is stored in c
However, if both operands are integers, then the division operator performs integer division. Effectively, this means any fractional component in the quotient is discarded.
int a = 3;
int b = 2;
int c = a / b; // 1 is stored in c
Since two integers are divided, the fraction (0.5) is truncated off the result. Even if you stored the result in a double
, you still wouldn't get the fractional part of the quotient.
int a = 3;
int b = 2;
double c = a / b; // 1.0 is stored in c
Let's take a closer look at this, as it can easily lead a novice programmer astray.
Division by zero also behaves differently depending on the data types of the operands.
public class FloatingDivision {
public static void main(String[] args) {
System.out.println(1.0 / 0.0); // floating-point division by zero
}
}
Floating-point division by zero produces a value of Infinity
.
$ java FloatingPoint
Infinity
On the other hand, integer division by zero produces a runtime exception.
public class IntegerDivision {
public static void main(String[] args) {
System.out.println(1 / 0); // integer division by zero
}
}
This code will compile just fine, but will crash when you run the program.
$ java IntegerDivision
Exception in thread "main" java.lang.ArithmeticException: / by zero
at IntegerDivision.main(IntegerDivision.java:3)
This is your first encounter with an exception. You've seen compile-time errors (i.e., typographical errors that prevent the program from compiling). A runtime error is a problem the code encounters while running.
Shortcuts
Shortcut operators combine the assignment operator (=
) with any of the simple arithmetic operators (+
, -
, *
, /
, or %
).
int a = 1;
int b = 2;
a += b; // equivalent to: a = a + b (which is 3)
a -= b; // equivalent to: a = a - b (which is 1)
a *= b; // equivalent to: a = a * b (which is 2)
a /= b; // equivalent to: a = a / b (which is 1)
a %= b; // equivalent to: a = a % b (which is 1)
As a matter of preference, some developers choose to be explicit while others opt for the shortcut assignments. One isn't more or less correct than the other, but it makes sense to be consistent in your code.
Increment and Decrement
Increasing or decreasing the value of a variable by one is a very common task in many programs. For that reason, Java provides a shortcut way of doing exactly that. The increment operator is ++
and the decrement operator is --
.
In postfix notation, the operator comes after the variable.
int x = 6;
x++; // x is now 7
x--; // x is 6 again
Alternatively, you might see prefix notation, where the operator comes before the variable.
int x = 6;
++x; // x is now 7
--x; // x is 6 again
They seemingly do the same thing, and that's true. But it's a little more complicated. When the variables are simultaneously involved in other operations, the timing of when the variable is incremented or decremented becomes a factor.
Prefix v. Postfix
Using postfix notation, the variable is incremented or decremented after the rest of the operation concludes.
public class Postfix {
public static void main(String[] args) {
int x = 1;
System.out.println(x);
System.out.println(x++);
System.out.println(x);
}
}
If you compile and run this program, you'll see the order in which the print statements and incrementing take place. In this example, the value of x
is printed to the console before its value is incremented from 1
to 2
.
$ java Postfix
1
1
2
On the other hand, the variable is incremented or decremented before the operation when using prefix notation.
public class Prefix {
public static void main(String[] args) {
int x = 1;
System.out.println(x);
System.out.println(++x);
System.out.println(x);
}
}
Now, try compiling and running this program. See the difference in when the value of x
is changed? It is incremented from 1
to 2
, and then it is printed to the console.
$ java Prefix
1
2
2
Make sure you understand why each of these examples behaves in the way that they do.
Conversions and Casting
There are several instances in which values are implicitly or explicitly converted from one data type to another. When dealing with binary operators (i.e., any of the simple arithmetic operators), the operands may or may not be implicitly converted.
If either operand is a
double
, the other one is converted to adouble
.If either operand is a
float
, the other one is converted to afloat
.If either operand is a
long
, the other one is converted to along
.Otherwise, both operands are converted to
int
s.
These implicit conversions do not affect the contents of any variables. The operands are converted only for the duration of the arithmetic operations.
Casting
In other circumstances, you may need to explicitly convert values to other data types. This is called casting. Suppose you wanted to truncate a number (i.e., retain only the whole number).
double decimalValue = 7.654;
int truncatedValue = (int) value;
(int)
tells the compiler to convert decimalValue
to an int
before storing it in truncatedValue
. Now, the final result will be 7
.
You can go in the other direction, too, in the event you wanted to treat an integer value as a real number.
int integerValue = 3;
double decimalValue = (double) integerValue;
integerValue
, of course, doesn't have a decimal component; however, the (double)
cast imposes one. After this conversion, decimalValue
will be 3.0
.
Possible Dangers
You need to be careful when casting, though. Since some data types cannot accommodate the same size or degree of precision, there is the potential for information loss. These are all safe conversions without the risk for any information loss. They are called widening conversions.
byte
⟶short
,int
,long
,float
, ordouble
short
⟶int
,long
,float
, ordouble
char
⟶int
,long
,float
, ordouble
int
⟶long
,float
, ordouble
long
⟶float
ordouble
float
⟶double
These, however, are not. They carry the very real risk for information loss. They're called narrowing conversions.
short
⟶byte
orchar
char
⟶byte
orshort
int
⟶byte
,short
, orchar
long
⟶byte
,short
,char
, orint
float
⟶byte
,short
,char
,int
, orlong
double
⟶byte
,short
,char
,int
,long
, orfloat
Go review the storage size and value ranges of the primitive data types if you're unsure why some casts are safe and some are unsafe.
Methods and Constants
The built-in Math
class provides a host of useful methods and constants for mathematical equations. To use these methods or fields, you need to reference the name of the class followed by the method or constant.
There are only two constants: 𝜋 and e.
Math.PI
Math.E
There are many more methods. I'll highlight some of the more common ones. Remember, though, the Math
class is a little bit different than some of the others we've seen.
The String
methods all required a String
object on which to call the method.
String s = "example";
int lenght = s.length(); // note the method is called on the object
Since the Math methods are static, there is no object. The methods are called on the class itself, and operator on values provided as parameters.
Math.abs(-5.5); // note the lack of any Math object, just the class
There are many methods, so I'll highlight some of the more common ones.
Method
Description
Usage
Math.abs
Computes the absolute value of a number.
Math.abs(-5.5); // 5.5
Math.cbrt
Computes the cube root of a value.
Math.cbrt(125); // 5.0
Math.ceil
Forcibly rounds a value up.
Math.ceil(6.1); // 7.0
Math.floor
Forcibly rounds a value down.
Math.floor(7.9); // 7.0
Math.hypot
Computes the hypotenuse given two side lengths.
Math.hypot(3, 4); // 5.0
Math.max
Determines the maximum of two values.
Math.max(1, 2); // 2
Math.min
Determines the minimum of two values.
Math.min(1, 2); // 1
Math.pow
Computes the value of one number raised to the power of another.
Math.pow(2, 3); // 8.0
Math.random
Generates a random number in the range [0.0, 1.0).
Math.random(); // 0.58961...
Math.round
Rounds a number up or down.
Math.round(4.3); // 4
Math.sqrt
Computes the square root of a value.
Math.sqrt(25); // 5.0
Check out the full documentation of the Math
class for all available methods. This video walks through a few of the more popular ones.
And as a bonus, here's a video on generating random numbers using the Math class. As odd as it might sounds, random numbers are a pretty popular choice of questions on AP exams.
And it might come in handy for an assignment or two, as well. Hint, hint...
Last updated
Was this helpful?