Skip to content

Operators



Why Do We Need Operators?

Variables store data, but programs are useless if they only act as digital filing cabinets. A program needs to process that data: calculating totals, comparing user input against a database, making logical decisions, and updating game states.

Operators let us perform actions on values, such as calculating, comparing, combining, and assigning them.


What Is an Operator?

Definition

At its core, every operation involves three concepts:

  • Operator: The symbol that tells the computer what action to perform (e.g., +).
  • Operand: The data or variables the operator acts upon (e.g., 5 and 3).
  • Expression: The combination of operators and operands that the computer evaluates to produce a single final value (e.g., 5 + 3).

Arithmetic Operators

These handle standard mathematical calculations.

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
  • Modulus (%): Returns the remainder of a division. 10 % 3 evaluates to 1.
  • Unary minus (-): Negates a single value (-x). The same symbol as subtraction, told apart by having one operand instead of two.

The Division Trap: In languages such as Java and C++, integer division produces an integer result. Python and JavaScript follow different rules.

Code
7 / 2    // 37 / 2.0  // 3.5

Making one operand a floating-point value changes the operation to floating-point division.

A DSA Trap: Integer Overflow

Even if your variables are large enough to hold individual values, adding them together might exceed what the type can hold before you get a chance to divide. For a 32-bit signed integer, the maximum is 2,147,483,647. The exact range depends on the type and the language, and so does what happens when a value goes past it: in Java, int arithmetic wraps around, while in C++ signed integer overflow is undefined behavior.

The single most common bug in binary search algorithms happens right here:

Code
int mid = (low + high) / 2;        // BUG: low + high can overflow the integer limitint mid = low + (high - low) / 2;  // CORRECT: Prevents overflow by subtracting first

Comparison Operators

Comparison operators ask a question about two values. In Java, C++, Python, and JavaScript, ordinary comparison expressions produce Boolean results (true/false, or True/False in Python).

  • Equal to (==)
  • Not equal to (!=)
  • Greater than (>)
  • Less than (<)
  • Greater than or equal to (>=)
  • Less than or equal to (<=)

Example: 5 >= 3 evaluates to true. 10 == 100 evaluates to false.


Logical Operators

Logical operators combine multiple Boolean values or comparisons to make complex decisions. The symbols differ by language:

Code
Java / C++ / JavaScript:&&   ||   ! Python:and  or   not
  • AND (&&): True only if both sides are true.
  • OR (||): True if at least one side is true.
  • NOT (!): Reverses the Boolean value. !true becomes false.

If you need to check if a number is between 1 and 10, you combine them: (x > 0) && (x <= 10).

Note

Python and JavaScript also have truth-value rules for non-Boolean values. We will explore those in more detail when we study Conditions.


Assignment and Compound Assignment

The assignment operator (=) takes the evaluated result from the right side and stores it in the variable on the left.

To save time, languages offer compound assignment operators that perform math and assignment in one step:

  • x += 5 is exactly the same as x = x + 5
  • x -= 2 is exactly the same as x = x - 2
  • x *= 10 is exactly the same as x = x * 10
  • x /= 2 is exactly the same as x = x / 2
  • x %= 3 is exactly the same as x = x % 3

Increment and Decrement

In languages such as Java, C++, and JavaScript, ++ and -- increment or decrement a value by 1. Python does not have them; there you write x += 1.

  • Increment: x++ or ++x (adds 1 to x)
  • Decrement: x-- or --x (subtracts 1 from x)

Pre vs. Post: The placement of the symbol matters when used inside a larger expression.

  • Pre-increment (++x): "Add 1 to x first, then use the new value in this expression."
  • Post-increment (x++): "Use the current value of x in this expression, and then add 1 to it right after."
Code
int a = 5;int b = a++;  // b gets 5, then a becomes 6int c = ++a;  // a becomes 7, then c gets 7

Prefer using ++ or -- on their own line when the value is being updated. This makes code easier to read and avoids confusing evaluation rules.


The Order of Operations

A Practical Precedence Guide

Just like PEMDAS/BODMAS in standard math, programming languages have a strict order of operations.

In the expression 2 + 3 * 4, multiplication has higher precedence than addition, so the answer is 14, not 20.

The exact precedence rules differ between languages. The broad ordering is similar for many common operators, but there is no single precedence table that is identical across Java, C++, Python, and JavaScript. A practical subset:

  1. Parentheses ()
  2. Unary operators (++, !, -)
  3. Multiplication / Division / Modulo (*, /, %)
  4. Addition / Subtraction (+, -)
  5. Relational (<, >, <=, >=)
  6. Equality (==, !=)
  7. Bitwise operators (&, ^, |)
  8. Logical AND (&&)
  9. Logical OR (||)
  10. Assignment (=, +=, etc.)

The Bitwise Precedence Trap: In Java, C++, and JavaScript, bitwise operators (&, |) have lower precedence than equality (==, !=). This causes massive bugs when students try to use bit manipulation.

If you want to check if a number is odd by checking its last bit, this will fail:

Code
if (n & 1 == 1)   // WRONGif ((n & 1) == 1) // CORRECT: The parentheses force the bitwise operation first

Because == has higher precedence than & in Java, the expression is grouped incorrectly.

Rule of thumb: Never memorize the entire precedence table. If you want an operation to happen first, or if you are mixing bitwise and relational operators, wrap it in parentheses: (2 + 3) * 4.

Associativity

When an expression has multiple operators with the exact same precedence, associativity breaks the tie.

  • Left-to-Right: Most operators group from left to right. 10 - 5 - 2 becomes (10 - 5) - 2, resulting in 3.
  • Right-to-Left: Assignment operators group from right to left. In x = y = 5, the y = 5 is grouped first, and then x is assigned the value of y.

Associativity determines how an expression is grouped; it does not necessarily determine the order in which operands are evaluated.

Expressions and Evaluation

An expression is any valid piece of code that resolves to a single value. The language first determines how the expression is grouped using precedence and associativity, then evaluates it according to its language rules.

Consider: result = 5 + 10 > 12

  1. Math first: 5 + 10 evaluates to 15.
  2. Comparison next: 15 > 12 evaluates to true.
  3. Assignment last: result is assigned the boolean value true.

Short-Circuit Evaluation

Logical AND and OR use short-circuit evaluation. In Java, C++, and JavaScript they are written && and ||; Python uses and and or. They evaluate expressions from left to right and stop as soon as the final result is known.

  • AND (&&): If the left side is false, the whole statement cannot possibly be true. The right side is completely ignored.
  • OR (||): If the left side is true, the whole statement is guaranteed to be true. The right side is ignored.

Why this matters: The operand on the right is never evaluated when the answer is already settled, which saves unnecessary work and can also keep your code from crashing. Look at this expression:

Code
if (x != 0 && 10 / x > 2)

If x is 0, the left side (0 != 0) is false. The && operator short-circuits and ignores the right side. If it hadn't short-circuited, the computer would have attempted 10 / 0, causing a fatal crash.


Conditional (Ternary) Operator

The ternary operator (? :) is the only operator that takes three operands. It evaluates a condition and produces one of two values.

Syntax: condition ? value_if_true : value_if_false

Code
int max = (a > b) ? a : b;

One trap belongs here. When the two results are true and false, the ternary is doing nothing at all:

Code
boolean isAdult = (age >= 18) ? true : false;  // redundantboolean isAdult = age >= 18;                   // the comparison IS the boolean

A comparison already evaluates to a boolean. The ternary adds unnecessary code without changing the result. Conditions covers when a ternary is the right shape and when an if-else ladder is.


Type Conversion and Operators

When an operator receives operands of different types, the language applies its own conversion rules. Some languages perform implicit conversions; others may reject the operation or apply different coercion rules.

In Java, if you add an integer 5 and a float 3.2, the computer temporarily promotes the 5 to 5.0 so the result is accurately 8.2.

However, if you force a floating-point value into an integer variable using explicit conversion, you lose information: int result = (int) 8.9; leaves you with 8. The fractional part is discarded; the value is not rounded.


Bitwise Operators: An Introduction

Bitwise operators work on the individual bits of an integer value.

  • Bitwise AND (&)
  • Bitwise OR (|)
  • Bitwise XOR (^)
  • Bitwise NOT (~)

They are useful in bit manipulation, masks and flags, low-level programming, and some algorithms. You will encounter them later in bit manipulation and certain DSA problems.

Shift Operators

<< and >> shift bits left or right.

For positive integers, shifting left by one bit often corresponds to multiplying by 2 when the result fits the integer type. Shifting right by one bit often corresponds to integer division by 2. Exact behavior depends on the language and the integer type.

We'll explore these more deeply when we study bit manipulation.


Operators Across Languages

The math is the same everywhere, but the syntax and some of the behavior vary:

  • Python: Does not use &&, ||, or !. It uses plain English words: and, or, not. Python also does not have ++ or -- operators; you must write x += 1.
  • Python Division: / always returns a float (even 4 / 2 gives 2.0). For integer division, you must use //.
  • JavaScript: Has both == (loose equality, allows type conversion) and === (strict equality, checks both value and type). You should almost always use === in JavaScript.
  • C++: Allows "operator overloading," meaning you can redefine what + means for custom objects.

JavaScript can also coerce values to different types depending on the operator, which can produce surprising results:

Code
"5" + 2   // "52""5" - 2   // 3

Common Mistakes

Watch out

  • Confusing = with ==: Writing if (x = 10) assigns 10 to x. Writing if (x == 10) actually asks the question.
  • Integer Division: Forgetting that 9 / 2 yields 4 in Java/C++.
  • Misunderstanding % with negatives: In C++ and Java, -5 % 3 yields -2. In Python, it yields 1. This is a major source of bugs in DSA when computing circular array indices or hash values with negative numbers. When using modulo for circular indexing, check the language's behavior for negative operands and normalize the result when necessary.
  • Unexpected Bitwise Precedence: Forgetting that == evaluates before &.
  • Confusing & with &&: & is a bitwise operator. && is a logical operator. Mixing them up causes strange bugs that don't trigger compile errors.

Operators in DSA

As you move into Data Structures and Algorithms, operators become your primary tools for logic:

  • % (Modulo) is heavily used to find even/odd numbers, manage circular arrays, and build hash tables.
  • && and || are essential for safe traversals (e.g., while (node != null && node.next != null)).
  • ++ and -- can update indices such as i, left and right as you move through arrays or other sequences.
  • +, -, / must be used carefully to avoid integer overflow (e.g., mid = low + (high - low) / 2).
  • <<, >>, &, and ^ are commonly used in bit manipulation and some specialized algorithms.

Quick Check

  1. In Java, why is int mid = (low + high) / 2; dangerous?
  2. What is the difference between x++ and ++x?
  3. In Java, why does if (n & 1 == 1) not mean what the programmer intended?
  4. Explain how short-circuit evaluation prevents a crash in this code: if (node != null && node.value == 10)
  5. In Java, if a is 4 and b is 5, why does a / b evaluate to 0?
Show answer
  1. Because low + high is worked out first, and on a large array that sum can exceed the range of the type. In Java, int overflow wraps around according to the type's fixed-width arithmetic. In languages such as C++, signed integer overflow has undefined behavior. low + (high - low) / 2 reaches the same midpoint without ever forming the large sum.
  2. Both add 1 to x. They differ only in what the surrounding expression receives: x++ hands over the old value and then increments, ++x increments and then hands over the new one. On a line by itself the two are identical.
  3. Because == has higher precedence than &, Java groups it as n & (1 == 1). This does not perform the intended bitwise check. Write (n & 1) == 1 to make the intended grouping explicit.
  4. && stops as soon as the answer is settled. If node is null, the left side is false, the whole expression is already false, and the right side is never evaluated, so node.value is never read.
  5. Because both are integers, so integer division discards the fraction. 4 / 5 is 0.8, truncated to 0. Make one side a floating-point value, as in 4.0 / b, to get 0.8.

Quick Recap

  • Operators perform calculations, assignments, and comparisons.
  • Arithmetic operators handle math, but beware of integer division truncation and integer overflow during addition.
  • In the languages covered here, comparison operators produce a Boolean result.
  • Logical operators (&&, ||) use short-circuit evaluation to skip unnecessary checks.
  • In Java, C++ and JavaScript, bitwise operators have lower precedence than equality operators, so use parentheses.
  • Assignment operators are right-associative in the languages discussed here, so expressions such as x = y = 5 group from right to left.
  • Precedence determines the order of operations; when in doubt, use parentheses.

Where This Leads

Code
Data Types     ↓Variables     ↓Operators     ↓Conditions     ↓Loops     ↓Functions

Operators give you the ability to calculate and compare values. The immediate next step is learning how to use those comparisons to make actual decisions. This brings us directly to Conditions (if/else statements), where we dictate which path our code will take.

Key takeaway

Operators are how programs work with values. The syntax is easy to learn; what matters is understanding how expressions are grouped, evaluated, and affected by the language's type rules. The traps worth carrying with you are integer division, overflow, negative modulo, type coercion, and precedence.