Step 1 of 5 · Reading · ~3 min
Learn
Getting Started
Numbers and Math
By the end of this lesson you can do arithmetic in C++ and get the right number out: you will know which type a calculation happens in, when int is too small, and how to get a fractional result from whole-number input.
The type of a result comes from its operands
An operand is a value an operator works on: in a / b, a and b are the operands. When both are int, C++ does the whole calculation in int, and int has no fractional part.
std::cout << 17 / 5 << "\n"; // 3 int / int truncates toward zero
std::cout << 17 % 5 << "\n"; // 2 % is the remainder
std::cout << 17 / 5.0 << "\n"; // 3.4 one double makes it double
std::cout << -17 / 5 << "\n"; // -3 toward zero, not down
Storing the result in a double afterwards does not help, because the truncation has already happened:
int bill = 25;
int people = 4;
double wrong = bill / people; // 6 (25/4 is 6, then 6.0)
double right = static_cast<double>(bill) / people; // 6.25
double alsoRight = bill / 4.0; // 6.25
static_cast<double>(x) converts x to double before the division runs. Where you put the cast matters: static_cast<double>(bill / people) converts the already-truncated 6, so it is still 6.
When int is too small
An int holds roughly -2.1 billion to +2.1 billion (2147483647 is the top). Multiplying two moderate numbers can pass that. Signed overflow is undefined behavior: the program may print a negative number, a wrapped number, or anything else.
int days = 30000;
int secondsPerDay = 86400;
long long bad = days * secondsPerDay; // overflow: computed in int, THEN widened
long long good = static_cast<long long>(days) * secondsPerDay; // 2592000000
Same rule as division: the operand types decide. If both factors are int, the product is int even when you store it in a long long. Either declare the inputs as long long from the start, or cast one factor before multiplying. long long holds about 9.2 x 10^18.
How std::cout prints a double
With no formatting set, std::cout prints a double with up to 6 significant digits and drops a useless .0:
std::cout << 6.25 << "\n"; // 6.25
std::cout << 8.0 << "\n"; // 8
std::cout << 12345.5 << "\n"; // 12345.5
Numbers with more than 6 significant digits switch to rounding or scientific notation; a later lesson, Output Formatting, covers <iomanip> for that. Every value in this lesson's exercise fits in 6 digits.
The math toolbox
#include <cmath>
#include <algorithm>
std::sqrt(49.0) // 7
std::pow(3, 4) // 81, returned as a double
std::abs(-2.5) // 2.5
std::max(8, 13) // 13 (from <algorithm>)
std::min(8, 13) // 8
Never compare two doubles with ==: 0.1 + 0.2 == 0.3 is false because those values are stored in binary, so they are slightly off. Check whether the difference is tiny instead, for example std::abs(x - y) < 1e-9.
Common mistakes
- Integer division for an average. Averaging 7 and 2 with only
intoperands gives4instead of4.5. One operand has to be adoublebefore the division runs. - Casting too late.
static_cast<double>(total / 2)prints4for the same input. The cast has to wrap an operand, not the finished quotient. - Multiplying two
ints that are too big. 65536 x 65536 overflowsintand typically prints0. Assigning the result to along longdoes not fix it. The operands must already belong long.
Your exercise
Given a rectangle's width and height, print its area and the mean of its two side lengths. The starter reads both numbers into int variables and prints placeholders. Sides go up to 100000, so check what type the area needs before you multiply.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…