Skip to content
Lesson 3 of 15

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 int operands gives 4 instead of 4.5. One operand has to be a double before the division runs.
  • Casting too late. static_cast<double>(total / 2) prints 4 for the same input. The cast has to wrap an operand, not the finished quotient.
  • Multiplying two ints that are too big. 65536 x 65536 overflows int and typically prints 0. Assigning the result to a long long does not fix it. The operands must already be long 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.

Up nextstd::stringStrings

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…