2. Week 1 Thursday: Integer Operations
≪ 1. Week 1 Tuesday: Getting Started | Table of Contents | 3. Week 2 Tuesday: Trouble with Doubles; Increments and Decrements ≫You are likely familiar with the arithmetic operations of +-*/
, representing addition, subtraction, multplication, and division, respectively. One can add, subtract, multiply, and divide integers in C++, alongside a handful of other fun new operations you may or may not have seen before.
Addition, subtraction, and multiplication work exactly how one expects them to, but integer division is somewhat different than usual. Consider the following snippet of code:
Following conventional wisdom and common core elementary math standards, one would expect the output to be something like 2
, 1.428571...
, and 0.71428571...
on three separate lines. However, the actual output is 2
, 1
, and 0
.
Integer Division and the Modulo Operator
Integer division in C++ will always produce an integer and not a decimal. If a division operation would mathematically be a decimal number, C++ will chop off everything past the decimal point and call it a day. This applies to negative numbers as well:
1cout << -9 / 6 << endl; // expected: -1.5, actual: -1
2cout << 9 / -6 << endl; // same as above ^^^
3cout << -21 / -4 << endl; // expected: 5.25, actual: 5
4// etc...
Although frustrating to learn about, this particular behaviour with integer division plays a central role in many algorithms, particularly those that need to chop up lists of data into a set number of chunks and in certain computations. An example is division by 10 — if i
is a C++ integer and one writes the code i = i / 10
, what does this do to i
? When might this be useful?
Integer division was born with a very talented brother named the modulo operator, %
. This is often introduced as the “remainder” operator, and although this is a perfect characterisation of what %
does for positive numbers, it is very misleading and produces confusion for expressions like 21 % -4
. What’s the remainder to 21 / -4
?
Instead, think about how division and multiplication are supposed to cancel each other out. Mathematically, if \(a\) and \(b\) are two numbers and \(b\) is nonzero, we expect
\[(a \div b)\times b = a,\]
no matter what. However, this is not the case in C++ — work out what (21 / 4) * 4
is using integer division. The modulo operator’s purpose is to capture this discrepancy! Specifically, if a
and b
are two integers (negative or not), the quantity a % b
is defined as the number satisfying the equation a = (a / b) * b + a % b
. When a
and b
are both positive, this is exactly the same thing as a remainder; however, when either a
or b
is negative (or both), this alternative form continues to be unambiguous.
Example 1.
Write a program that expresses 1999473 seconds as days, hours, minutes, and seconds.
We’ll do this in steps: we’ll first write 1999473 seconds in minutes and seconds. Since there are 60 seconds to a minute, and since \(1999473\div 60 = 33324.55\), there should be 33324 minutes and some leftover seconds. This 33324 is the result of doing integer division! We divided the number of seconds by \(60\), then chopped off the decimal. We can then use the modulo operator to extract the number of seconds, which should be the remainder of this division.
We can then turn 33324 minutes into hours and minutes, then however many hours into days and hours! In pseudocode:
- Define an integer variable
seconds
and set it to1999473
. - Set
minutes = seconds / 60
and replaceseconds
withseconds % 60
. - Set
hours = minutes / 60
and replaceminutes
withminutes % 60
. - Set
days = hours / 24
and replacehours
withhours % 24
. - Print out the results to the screen.
Here’s the whole thing converted to C++
code:
1#include <iostream>
2
3using namespace std;
4
5int main() {
6 // step 1
7 int seconds = 1999473;
8
9 // step 2
10 int minutes = seconds / 60;
11 seconds = seconds % 60;
12
13 // step 3
14 int hours = minutes / 60;
15 minutes = minutes % 60;
16
17 // step 4
18 int days = hours / 24;
19 hours = hours % 24;
20
21 // step 5
22 cout << "There are " << days << " days, "
23 << hours << " hours, "
24 << minutes << " minutes, and "
25 << seconds << " seconds in 1999473 seconds." << endl;
26
27 return 0;
28}
Some things to note about this:
- Every time we set up a variable for the first time, we need to specify that it’s an
int
. But every time we overwrite the contents of a variable, we no longer need to do this. - Note the extra spaces in the code for step 5. This is to ensure that the numbers are separated from the words when they’re printed out.
- Note also that I’ve split up the pieces of the
cout
onto separate lines, without the semicolons. The compiler recognises that each of these lines is part of the same command, and semicolons only go at the end of a command.
Problem 2.
Write a program that expresses 302469 inches as miles, feet, and inches.