Two kinds of division on one operator
Integer division is not a C++ quirk to memorize. CPUs have separate circuits for integer and floating-point math, and / maps directly onto whichever instruction the operand types select. Knowing which one you are invoking is the entire lesson.
It matters in practice because the failure is silent. An average that comes out as 3 instead of 3.5 corrupts a result without crashing anything, which makes it one of the hardest bug types to notice.
Operators you already know, one trap you do not
The operators + - * / % work as in Python, with one enormous exception:
Dividing two ints throws away the decimal part.
7 / 2 // 3 (int / int = int, truncated toward zero) 7.0 / 2 // 3.5 (if either side is a double, the result is a double) 7 % 2 // 1 (remainder, ints only)
Python's / always gives a float and // truncates. C++ has only /, and it decides which behavior to use from the types of its operands. This is the number one beginner bug in C++ arithmetic.
Compound assignment is familiar from Python: x += 5, x -= 2, x *= 3. New here are x++, which adds 1, and x--, which subtracts 1. There is no ** power operator, so raising to a power uses std::pow(a, b) from <cmath>.
The same numbers, two different divisions
Four expressions built from 7, 2, 10, and 3. The first two use identical numbers and produce different answers purely because of type.
#include <iostream> int main() { std::cout << 7 / 2 << "\n"; // int / int std::cout << 7.0 / 2 << "\n"; // double / int std::cout << 7 % 2 << "\n"; // remainder std::cout << 10 % 3 << "\n"; return 0; }
Output
3 3.5 1 1
Writing 7.0 instead of 7 is the whole difference between lines one and two. Once either operand is a double, the other one is promoted to double as well and the division is done in floating point.
The last two lines both give 1, and that coincidence is worth pulling apart. 7 % 2 is 1 because 2 goes into 7 three times with 1 left over, and 10 % 3 is 1 because 3 goes into 10 three times with 1 left over. The % operator works on integers only, and applying it to a double is a compile error rather than a rounding surprise.
Casting: converting between types on purpose
Sometimes both values are ints but you want real division. Cast one operand to double:
int total = 7, count = 2; double avg = static_cast<double>(total) / count; // 3.5
static_cast<T>(value) is the modern C++ cast: explicit, searchable, and checked by the compiler. You may see C-style casts like (double)total in old code. They work, but prefer static_cast.
Casts also go the other way, and truncate:
double price = 9.99; int dollars = static_cast<int>(price); // 9, the .99 is dropped
Some conversions happen implicitly (int → double is safe and automatic). Narrowing ones (double → int) are where you should be explicit, so readers know the data loss is intentional.
Dividing two int variables
With int a = 9; and int b = 4;, the statement std::cout << a / b; prints 2.
Both operands are int, so / performs integer division and truncates 2.25 down to 2. Truncation always moves toward zero rather than rounding, so the result is 2 and not 3, even though 2.25 is closer to 2 anyway. For negative values the same rule gives -9 / 4 as -2.
Getting 2.25 requires making at least one operand a double, for example static_cast<double>(a) / b. The operator inspects the operand types and nothing else, so intent has no influence on the result.
Expression with a = 9, b = 4 | Result | Why |
|---|---|---|
a / b | 2 | both int, so integer division |
a % b | 1 | remainder after 2 whole fits |
static_cast<double>(a) / b | 2.25 | one side is double, so real division |
a / 4.0 | 2.25 | the literal is a double |
static_cast<double>(a / b) | 2 | the damage happened inside the parentheses |
That last row is the trap inside the trap. Casting the result of an integer division cannot recover the lost decimals, because the truncation already happened. The cast has to be applied to an operand.
An average that needs a cast
Reading two integers and dividing them is where this bug shows up most often, because scores and counts are naturally whole numbers while their average usually is not.
#include <iostream> int main() { int points, games; std::cin >> points >> games; std::cout << "Average: " << static_cast<double>(points) / games << "\n"; return 0; }
Input
7 2
Output
Average: 3.5Writing points / games alone would print 3, since both variables are int. The cast on the left operand promotes the whole expression to floating point, and games is converted automatically to match it.
Only one operand needs the cast, which is worth knowing because casting both, as static_cast<double>(points) / static_cast<double>(games), is correct but noisier. This example also declares two variables on one line, int points, games;, which is a legal shorthand and common in competitive code.
Where the truncation actually happens
This version stores the average in a double variable rather than printing it directly, which makes the timing of the truncation clear.
#include <iostream> int main() { int total = 17, count = 4; double avg = static_cast<double>(total) / count; std::cout << avg << "\n"; return 0; }
Output
4.25The declared type of avg does not protect the calculation. Written as double avg = total / count;, the right-hand side is evaluated first, in int arithmetic, producing 4, and only then is that 4 converted to 4.0 and stored. The variable being a double arrives one step too late to help.
That ordering is the general rule for expressions in C++: each operator picks its behavior from its own operands, with no regard for where the result is heading. Casting inside the expression, as this code does, is the only way to change what the division does.