Ch 3.3 Arithmetic Operators
Arithmetic operators include the four basic operations (+, -, *, /) and the remainder operation (%). While they seem simple, there are many important concepts to understand: implicit type conversion, integer overflow, and floating-point precision.
1. Arithmetic Operators Overview
| Operator | Name | Example | Result |
|---|---|---|---|
+ | Addition / String concatenation | 3 + 4 | 7 |
- | Subtraction | 10 - 3 | 7 |
* | Multiplication | 4 * 5 | 20 |
/ | Division | 10 / 3 | 3 (integer truncation) |
% | Remainder | 10 % 3 | 1 |
2. Addition Operator (+): Numeric Addition + String Concatenation
The + operator has two roles in Java.
- Numeric addition: Adds two numbers.
- String concatenation: If either operand is a
String, the other is converted to a string and they are joined.
public class PlusOperator {
public static void main(String[] args) {
// Numeric addition
int a = 10, b = 20;
System.out.println(a + b); // 30
// String concatenation: if one side is String, the other is automatically converted
String hello = "Hello";
System.out.println(hello + 42); // "Hello42"
System.out.println(hello + " " + "World"); // "Hello World"
System.out.println("Age: " + a); // "Age: 10"
}
}
Difference Based on Order (Associativity)
The + operator is left-associative (left-to-right). Therefore, the order of operands can completely change the result.
public class PlusOrder {
public static void main(String[] args) {
// 1 + 2 = 3 (numeric) -> 3 + "3" = "33" (string concatenation)
System.out.println(1 + 2 + "3"); // "33"
// "1" + 2 = "12" (string concat) -> "12" + 3 = "123" (string concat)
System.out.println("1" + 2 + 3); // "123"
// "1" + (2 + 3) = "1" + 5 = "15" (add with parentheses first)
System.out.println("1" + (2 + 3)); // "15"
// Calculate numbers first then convert to string
int x = 5, y = 10;
System.out.println("Sum: " + (x + y)); // "Sum: 15" (parentheses required!)
System.out.println("Sum: " + x + y); // "Sum: 510" (unexpected result!)
}
}
"Sum: " + x + y becomes "Sum: 5" + 10 = "Sum: 510".
To add numbers first, use parentheses like "Sum: " + (x + y).
3. Subtraction (-) and Multiplication (*)
These work the same as standard mathematical operations.
public class SubMul {
public static void main(String[] args) {
int a = 15, b = 4;
// Subtraction
System.out.println(a - b); // 11
System.out.println(b - a); // -11 (negative is possible)
// Multiplication
System.out.println(a * b); // 60
// Floating-point operations
double x = 3.14, r = 5.0;
double area = x * r * r; // Area of circle (pi * r^2)
System.out.printf("Circle area: %.2f%n", area); // 78.50
}
}
4. Division Operator (/)
Integer Division: Truncation
When both operands are integer types, the result is also an integer. The decimal part is truncated (not rounded).
System.out.println(10 / 4); // 2 (truncated, NOT rounded)
System.out.println(-10 / 3); // -3 (truncated toward zero)
System.out.println(7 / 2); // 3
System.out.println(1 / 2); // 0
Floating-Point Division: Includes Decimal
If at least one operand is a floating-point type, the result is also floating-point.
System.out.println(10 / 4.0); // 2.5 (one side is double -> result is also double)
System.out.println(10.0 / 4); // 2.5
System.out.println((double)10 / 4); // 2.5 (explicit cast)
Division by Zero
public class DivisionByZero {
public static void main(String[] args) {
// Dividing an integer by 0 throws ArithmeticException (runtime error)
// System.out.println(5 / 0); // ArithmeticException: / by zero
// Dividing a float by 0 returns Infinity or NaN
System.out.println(5.0 / 0.0); // Infinity
System.out.println(-5.0 / 0.0); // -Infinity
System.out.println(0.0 / 0.0); // NaN (Not a Number)
// Check for Infinity and NaN
double result = 5.0 / 0.0;
System.out.println(Double.isInfinite(result)); // true
System.out.println(Double.isNaN(0.0 / 0.0)); // true
}
}
Floating-point division returns Infinity without throwing an exception, but integer division throws ArithmeticException. When dividing by user-provided values, always check for zero first.
int divisor = getUserInput();
if (divisor != 0) {
System.out.println(100 / divisor);
} else {
System.out.println("Cannot divide by zero.");
}
5. Remainder Operator (%)
Returns the remainder when the left operand is divided by the right operand.
public class ModuloOperator {
public static void main(String[] args) {
System.out.println(10 % 3); // 1
System.out.println(10 % 5); // 0 (evenly divisible)
System.out.println(7 % 2); // 1
System.out.println(3 % 10); // 3 (dividend < divisor)
}
}
Negative Operands and Remainder
In Java, the sign of the % result follows the sign of the left operand (dividend).
System.out.println(10 % 3); // 1
System.out.println(-10 % 3); // -1 (dividend is negative, so result is negative)
System.out.println(10 % -3); // 1 (dividend is positive, so result is positive)
System.out.println(-10 % -3); // -1
Math.floorMod vs %
If you want a mathematically correct remainder (always positive), use Math.floorMod().
System.out.println(-7 % 3); // -1 (Java % operator)
System.out.println(Math.floorMod(-7, 3)); // 2 (mathematical remainder, always positive)
Practical Uses of the Remainder Operator
public class ModuloUsage {
public static void main(String[] args) {
// Check even/odd
for (int i = 1; i <= 10; i++) {
String type = (i % 2 == 0) ? "even" : "odd";
System.out.println(i + ": " + type);
}
// Check multiples
int n = 36;
System.out.println(n + " is a multiple of 3: " + (n % 3 == 0)); // true
System.out.println(n + " is a multiple of 7: " + (n % 7 == 0)); // false
// Circular index (0, 1, 2, 0, 1, 2, ...)
int size = 3;
for (int i = 0; i < 9; i++) {
System.out.print((i % size) + " "); // 0 1 2 0 1 2 0 1 2
}
System.out.println();
// Extract digits
int number = 12345;
System.out.println("Units digit: " + (number % 10)); // 5
System.out.println("Tens digit: " + (number / 10 % 10)); // 4
}
}
6. Implicit Type Conversion Rules in Arithmetic
When operands of different types are used in an operation, Java automatically converts (promotes) to the larger (more precise) type.
| Operand Type Combination | Result Type |
|---|---|
byte + byte | int |
short + short | int |
int + long | long |
int + float | float |
long + float | float |
float + double | double |
Any number + String | String |
public class TypePromotion {
public static void main(String[] args) {
byte b = 10;
short s = 20;
int i = 30;
long l = 40L;
float f = 1.5f;
double d = 2.5;
// byte + short -> int
int r1 = b + s;
System.out.println("byte+short = " + r1); // 30 (int)
// int + long -> long
long r2 = i + l;
System.out.println("int+long = " + r2); // 70 (long)
// int + float -> float
float r3 = i + f;
System.out.println("int+float = " + r3); // 31.5 (float)
// long + double -> double
double r4 = l + d;
System.out.println("long+double = " + r4); // 42.5 (double)
}
}
7. Integer Overflow and Solutions
When an integer variable exceeds its representable range, overflow occurs and produces unexpected values.
public class OverflowExample {
public static void main(String[] args) {
// int max: 2,147,483,647
int max = Integer.MAX_VALUE;
System.out.println("int max: " + max); // 2147483647
System.out.println("max + 1: " + (max + 1)); // -2147483648 (overflow!)
// Real-world problem: sum of two large numbers
int a = 2_000_000_000;
int b = 2_000_000_000;
int wrong = a + b; // Overflow occurs!
System.out.println("Wrong sum: " + wrong); // Prints a negative number
// Solution 1: Use long type
long correct = (long) a + b;
System.out.println("Correct sum: " + correct); // 4000000000
// Solution 2: Use Math.addExact() (throws ArithmeticException on overflow)
try {
int safeResult = Math.addExact(a, b);
System.out.println(safeResult);
} catch (ArithmeticException e) {
System.out.println("Overflow detected! Use long type.");
}
// Math.multiplyExact and Math.subtractExact work the same way
}
}
8. Floating-Point Precision Issues and BigDecimal
Computers represent real numbers in binary, so some decimal values cannot be represented exactly.
public class FloatingPointPrecision {
public static void main(String[] args) {
// Famous floating-point issue
System.out.println(0.1 + 0.2); // 0.30000000000000004 (!)
System.out.println(0.1 + 0.2 == 0.3); // false
// double has approximately 15~16 significant digits
System.out.println(1.0 / 3.0); // 0.3333333333333333 (repeating decimal truncated)
// Solution 1: Epsilon (tolerance) comparison
double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 1e-10;
System.out.println(Math.abs(a - b) < epsilon); // true
// Solution 2: BigDecimal (for precise calculation)
java.math.BigDecimal bd1 = new java.math.BigDecimal("0.1");
java.math.BigDecimal bd2 = new java.math.BigDecimal("0.2");
java.math.BigDecimal bd3 = bd1.add(bd2);
System.out.println(bd3); // 0.3 (exact!)
System.out.println(bd3.equals(new java.math.BigDecimal("0.3"))); // true
}
}
- Financial calculations (money)
- Tax and interest rate calculations
- When exact decimal places are required
General scientific calculations or game physics can use double just fine.
9. Key Methods of the Math Class
The java.lang.Math class provides static methods for mathematical operations. It can be used directly without an import.
public class MathMethods {
public static void main(String[] args) {
// Absolute value
System.out.println(Math.abs(-15)); // 15
System.out.println(Math.abs(15)); // 15
// Max and min
System.out.println(Math.max(10, 20)); // 20
System.out.println(Math.min(10, 20)); // 10
// Power: pow(base, exponent)
System.out.println(Math.pow(2, 10)); // 1024.0
System.out.println(Math.pow(3, 3)); // 27.0
// Square root
System.out.println(Math.sqrt(16)); // 4.0
System.out.println(Math.sqrt(2)); // 1.4142135623730951
// Ceiling, floor, rounding
System.out.println(Math.ceil(3.1)); // 4.0 (ceil: toward +infinity)
System.out.println(Math.ceil(-3.9)); // -3.0 (ceil: toward 0)
System.out.println(Math.floor(3.9)); // 3.0 (floor: toward -infinity)
System.out.println(Math.floor(-3.1)); // -4.0 (floor: toward -infinity)
System.out.println(Math.round(3.5)); // 4 (round -> returns long/int)
System.out.println(Math.round(3.49)); // 3
// Logarithm and exponent
System.out.println(Math.log(Math.E)); // 1.0 (natural log ln(e))
System.out.println(Math.log10(1000)); // 3.0 (common log)
System.out.println(Math.exp(1)); // 2.718... (e^1)
// Trigonometric functions (radians)
System.out.printf("sin(90 deg) = %.1f%n", Math.sin(Math.PI / 2)); // 1.0
System.out.printf("cos(0 deg) = %.1f%n", Math.cos(0)); // 1.0
// Random value: 0.0 (inclusive) to 1.0 (exclusive)
double rand = Math.random();
System.out.println("Random: " + rand);
// Dice simulation (1~6)
int dice = (int)(Math.random() * 6) + 1;
System.out.println("Dice: " + dice);
// PI and E constants
System.out.println("PI = " + Math.PI); // 3.141592653589793
System.out.println("E = " + Math.E); // 2.718281828459045
}
}
10. Practical Example: BMI Calculator
import java.util.Scanner;
public class BMICalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter height (cm): ");
double heightCm = scanner.nextDouble();
System.out.print("Enter weight (kg): ");
double weight = scanner.nextDouble();
// BMI calculation: weight(kg) / height(m)^2
double heightM = heightCm / 100.0; // cm -> m
double bmi = weight / (heightM * heightM);
// Display with 2 decimal places
System.out.printf("%n===== BMI Result =====%n");
System.out.printf("Height: %.1f cm%n", heightCm);
System.out.printf("Weight: %.1f kg%n", weight);
System.out.printf("BMI: %.2f%n", bmi);
// BMI classification (WHO standard)
String category;
if (bmi < 18.5) {
category = "Underweight";
} else if (bmi < 23.0) {
category = "Normal";
} else if (bmi < 25.0) {
category = "Overweight";
} else if (bmi < 30.0) {
category = "Obese Class I";
} else {
category = "Obese Class II+";
}
System.out.println("Category: " + category);
// Normal weight range calculation
double minWeight = 18.5 * heightM * heightM;
double maxWeight = 22.9 * heightM * heightM;
System.out.printf("Normal weight range: %.1f kg ~ %.1f kg%n", minWeight, maxWeight);
// Difference to target weight
double targetWeight = 22.0 * heightM * heightM; // Middle of normal range
double diff = targetWeight - weight;
if (Math.abs(diff) < 0.5) {
System.out.println("You are at an ideal weight!");
} else if (diff > 0) {
System.out.printf("Need to gain %.1f kg to reach target weight.%n", diff);
} else {
System.out.printf("Need to lose %.1f kg to reach target weight.%n", Math.abs(diff));
}
scanner.close();
}
}
Sample output (height 175cm, weight 70kg):
Enter height (cm): 175
Enter weight (kg): 70
===== BMI Result =====
Height: 175.0 cm
Weight: 70.0 kg
BMI: 22.86
Category: Normal
Normal weight range: 56.7 kg ~ 70.0 kg
You are at an ideal weight!
11. Key Summary
| Topic | Key Content |
|---|---|
| Integer division | Decimal truncation; cast to (double) if a decimal result is needed |
| Division by zero | Integer: ArithmeticException; Float: Infinity / NaN |
String + | Result varies by order; use parentheses for numeric sums |
| Implicit conversion | Automatically promotes to larger type (int -> long -> float -> double) |
| Overflow | Use long or Math.addExact() for safe handling |
| Floating-point | 0.1 + 0.2 != 0.3; use BigDecimal for financial calculations |
| Math class | abs, max, min, pow, sqrt, ceil, floor, round |