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.,
5and3). - 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 % 3evaluates to1. - 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.
7 / 2 // 37 / 2.0 // 3.5Making 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:
int mid = (low + high) / 2; // BUG: low + high can overflow the integer limitint mid = low + (high - low) / 2; // CORRECT: Prevents overflow by subtracting firstComparison 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:
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.!truebecomesfalse.
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 += 5is exactly the same asx = x + 5x -= 2is exactly the same asx = x - 2x *= 10is exactly the same asx = x * 10x /= 2is exactly the same asx = x / 2x %= 3is exactly the same asx = 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 toxfirst, then use the new value in this expression." - Post-increment (
x++): "Use the current value ofxin this expression, and then add 1 to it right after."
int a = 5;int b = a++; // b gets 5, then a becomes 6int c = ++a; // a becomes 7, then c gets 7Prefer 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:
- Parentheses
() - Unary operators (
++,!,-) - Multiplication / Division / Modulo (
*,/,%) - Addition / Subtraction (
+,-) - Relational (
<,>,<=,>=) - Equality (
==,!=) - Bitwise operators (
&,^,|) - Logical AND (
&&) - Logical OR (
||) - 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:
if (n & 1 == 1) // WRONGif ((n & 1) == 1) // CORRECT: The parentheses force the bitwise operation firstBecause == 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 - 2becomes(10 - 5) - 2, resulting in3. - Right-to-Left: Assignment operators group from right to left. In
x = y = 5, they = 5is grouped first, and thenxis assigned the value ofy.
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
- Math first:
5 + 10evaluates to15. - Comparison next:
15 > 12evaluates totrue. - Assignment last:
resultis assigned the boolean valuetrue.
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 isfalse, the whole statement cannot possibly be true. The right side is completely ignored. - OR (
||): If the left side istrue, 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:
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
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:
boolean isAdult = (age >= 18) ? true : false; // redundantboolean isAdult = age >= 18; // the comparison IS the booleanA 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 writex += 1. - Python Division:
/always returns a float (even4 / 2gives2.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:
"5" + 2 // "52""5" - 2 // 3Common Mistakes
Watch out
- Confusing
=with==: Writingif (x = 10)assigns 10 to x. Writingif (x == 10)actually asks the question. - Integer Division: Forgetting that
9 / 2yields4in Java/C++. - Misunderstanding
%with negatives: In C++ and Java,-5 % 3yields-2. In Python, it yields1. 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 asi,leftandrightas 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
- In Java, why is
int mid = (low + high) / 2;dangerous? - What is the difference between
x++and++x? - In Java, why does
if (n & 1 == 1)not mean what the programmer intended? - Explain how short-circuit evaluation prevents a crash in this code:
if (node != null && node.value == 10) - In Java, if
ais 4 andbis 5, why doesa / bevaluate to0?
Show answerHide answer
- Because
low + highis worked out first, and on a large array that sum can exceed the range of the type. In Java,intoverflow wraps around according to the type's fixed-width arithmetic. In languages such as C++, signed integer overflow has undefined behavior.low + (high - low) / 2reaches the same midpoint without ever forming the large sum. - Both add 1 to
x. They differ only in what the surrounding expression receives:x++hands over the old value and then increments,++xincrements and then hands over the new one. On a line by itself the two are identical. - Because
==has higher precedence than&, Java groups it asn & (1 == 1). This does not perform the intended bitwise check. Write(n & 1) == 1to make the intended grouping explicit. &&stops as soon as the answer is settled. Ifnodeis null, the left side is false, the whole expression is already false, and the right side is never evaluated, sonode.valueis never read.- Because both are integers, so integer division discards the fraction.
4 / 5is0.8, truncated to0. Make one side a floating-point value, as in4.0 / b, to get0.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 = 5group from right to left. - Precedence determines the order of operations; when in doubt, use parentheses.
Where This Leads
Data Types ↓Variables ↓Operators ↓Conditions ↓Loops ↓FunctionsOperators 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.