Skip to main content

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

OperatorNameExampleResult
+Addition / String concatenation3 + 47
-Subtraction10 - 37
*Multiplication4 * 520
/Division10 / 33 (integer truncation)
%Remainder10 % 31

2. Addition Operator (+): Numeric Addition + String Concatenation

The + operator has two roles in Java.

  1. Numeric addition: Adds two numbers.
  2. 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!)
}
}
Always use parentheses when appending a numeric sum to a string

"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
}
}
Always check for zero before integer division

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 CombinationResult Type
byte + byteint
short + shortint
int + longlong
int + floatfloat
long + floatfloat
float + doubledouble
Any number + StringString
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
}
}
When should you use BigDecimal?
  • 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

TopicKey Content
Integer divisionDecimal truncation; cast to (double) if a decimal result is needed
Division by zeroInteger: ArithmeticException; Float: Infinity / NaN
String +Result varies by order; use parentheses for numeric sums
Implicit conversionAutomatically promotes to larger type (int -> long -> float -> double)
OverflowUse long or Math.addExact() for safe handling
Floating-point0.1 + 0.2 != 0.3; use BigDecimal for financial calculations
Math classabs, max, min, pow, sqrt, ceil, floor, round