- 4.1 Introduction
- 4.2 Essentials of Counter-Controlled Iteration
- 4.3 for Iteration Statement
- 4.4 Examples Using the for Statement
- 4.5 Application: Summing Even Integers
- 4.6 Application: Compound-Interest Calculations
- 4.7 do... while Iteration Statement
- 4.8 switch Multiple-Selection Statement
- 4.9 C++17 Selection Statements with Initializers
- 4.10 break and continue Statements
- 4.11 Logical Operators
- 4.12 Confusing the Equality (==) and Assignment (=) Operators
- 4.13 Objects-Natural Case Study: Using the miniz-cpp Library to Write and Read ZIP files
- 4.14 C++20 Text Formatting with Field Widths and Precisions
- 4.15 Wrap-Up
4.6 Application: Compound-Interest Calculations
Let’s compute compound interest with a for statement. Consider the following problem:
A person invests $1,000 in a savings account yielding 5% interest. Assuming all interest is left on deposit, calculate and print the amount of money in the account at the end of each year for 10 years. Use the following formula to determine the amounts:
a = p (1 + r)n
where
p is the original amount invested (i.e., the principal),
r is the annual interest rate (e.g., use 0.05 for 5%),
n is the number of years, and
a is the amount on deposit at the end of the nth year.
The solution (Fig. 4.4) uses a loop to perform the calculation for each of the 10 years the money remains on deposit. We use double values here for the monetary calculations. Then we discuss the problems with using floating-point types to represent monetary amounts. For financial applications that require precise monetary calculations and rounding control, consider using an open-source library such as Boost.Multiprecision.1
Lines 12–13 initialize double variable principal to 1000.00 and double variable rate to 0.05. C++ treats floating-point literals like 1000.00 and 0.05 as type double. Similarly, C++ treats whole numbers like 7 and -22 as type int.2 Lines 15–16 display the initial principal and the interest rate.
1 // fig04_04.cpp 2 // Compound-interest calculations with for. 3 #include <iostream> 4 #include <iomanip> 5 #include <cmath> // for pow function 6 using namespace std; 7 8 int main() { 9 // set floating-point number format 10 cout << fixed << setprecision(2); 11 12 double principal{1000.00}; // initial amount before interest 13 double rate{0.05}; // interest rate 14 15 cout << "Initial principal: " << principal << "\n"; 16 cout << " Interest rate: " << rate << "\n"; 17 18 // display headers 19 cout << "\nYear" << setw(20) << "Amount on deposit" << "\n"; 20 21 // calculate amount on deposit for each of ten years 22 for (int year{1}; year <= 10; ++year) { 23 // calculate amount on deposit at the end of the specified year 24 double amount{principal * pow(1.0 + rate, year)} ; 25 26 // display the year and the amount 27 cout << setw(4) << year << setw(20) << amount << "\n"; 28 } 29 }
Initial principal: 1000.00 Interest rate: 0.05 Year Amount on deposit 1 1050.00 2 1102.50 3 1157.63 4 1215.51 5 1276.28 6 1340.10 7 1407.10 8 1477.46 9 1551.33 10 1628.89
Fig. 4.4 Compound-interest calculations with for.
Formatting with Field Widths and Justification
Line 10 before the loop and line 27 in the loop combine to print the year and amount values. We specify the formatting with the parameterized stream manipulators setprecision and setw and the nonparameterized stream manipulator fixed. The stream manipulator setw(4) specifies that the next value output should appear in a field width of 4—i.e., cout << prints the value with at least four character positions. If the value to be output requires fewer than four character positions, the value is right-aligned in the field by default. If the value to be output has more than four character positions, C++ extends the field width to the right to accommodate the entire value. To left-align values, output non-parameterized stream manipulator left (found in header <iostream>). You can restore right-alignment by outputting nonparameterized stream manipulator right.
The other formatting in the output statements displays variable amount as a fixed-point value with a decimal point (fixed in line 10) right-aligned in a field of 20 character positions (setw(20) in line 27) and two digits of precision to the right of the decimal point (setprecision(2) in line 10). We applied the sticky stream manipulators fixed and set-precision to the output stream cout before the for loop because these format settings remain in effect until they’re changed, and they do not need to be applied during each iteration of the loop. However, the field width specified with setw applies only to the next value output. Chapter 19 discusses cin’s and cout’s formatting capabilities in detail. We continue discussing C++20’s powerful new text-formatting capabilities in Section 4.14.
Performing the Interest Calculations with Standard Library Function pow
The for statement (lines 22–28) iterates 10 times, varying the int control variable year from 1 to 10 in increments of 1. Variable year represents n in the problem statement.
C++ does not include an exponentiation operator, so we use the standard library function pow (line 24) from the header <cmath> (line 5). The call pow(x, y) calculates the value of x raised to the yth power. The function receives two double arguments and returns a double value. Line 24 performs the calculation a = p(1 + r)n, where a is amount, p is principal, r is rate and n is year.
Perf Function pow’s first argument—the calculation 1.0 + rate—produces the same result each time through the loop, so repeating it in every iteration of the loop is wasteful. To improve program performance, many of today’s optimizing compilers place such calculations before loops in the compiled code.
Floating-Point Number Precision and Memory Requirements
A float represents a single-precision floating-point number. Most of today’s systems store these in four bytes of memory with approximately seven significant digits. A double represents a double-precision floating-point number. Most of today’s systems store these in eight bytes of memory with approximately 15 significant digits—approximately double the precision of floats. Most programmers use type double. C++ treats floating-point numbers such as 3.14159 in a program’s source code as double values by default. Such values in the source code are known as floating-point literals.
The C++ standard requires only that type double provide at least as much precision as float. There is also type long double, which provides at least as much precision as double. For a complete list of C++ fundamental types and their typical ranges, see
https://en.cppreference.com/w/cpp/language/types
Floating-Point Numbers Are Approximations
Err In conventional arithmetic, floating-point numbers often arise as a result of division. Dividing 10 by 3, the result is 3.3333333…, with the sequence of 3s repeating infinitely. The computer allocates a fixed amount of space to hold such a value, so the stored value can be only an approximation. Floating-point types such as double suffer from what is referred to as representational error. Assuming that floating-point numbers are represented exactly (e.g., using them in comparisons for equality) can lead to incorrect results.
Floating-point numbers have numerous applications, especially for measured values. For example, when we speak of a “normal” body temperature of 98.6 degrees Fahrenheit, we do not need to be precise to a large number of digits. When we read the temperature on a thermometer as 98.6, it actually might be 98.594732103. Calling this number 98.6 is fine for most body temperature calculations. Generally, double is preferred over float, because doubles represent floating-point numbers more precisely.3
A Warning about Displaying Rounded Values
This example declared double variables amount, principal and rate to be of type double. Unfortunately, floating-point numbers can cause trouble with fractional dollar amounts. Here’s a simple explanation of what can go wrong when floating-point numbers are used to represent dollar amounts that are displayed with two digits to the right of the decimal point. Two calculated dollar amounts stored in the machine could be 14.234 (rounded to 14.23 for display purposes) and 18.673 (rounded to 18.67 for display purposes). When these amounts are added, they produce the internal sum 32.907, which would typically be rounded to 32.91 for display purposes. Thus, your output could appear as

but a person adding the individual numbers as displayed would expect the sum to be 32.90. You’ve been warned!
Even Common Dollar Amounts Can Have Floating-Point Representational Errors
Even simple dollar amounts can have representational errors when they’re stored as doubles. To see this, we created a simple program that defined the variable d as follows:
double d{123.02};
We displayed d’s value with 20 digits of precision to the right of the decimal point. The resulting output showed 123.02 as 123.0199999…, which is another example of a representational error. Though some dollar amounts can be represented precisely as doubles, many cannot. This is a common problem in many programming languages. Later in the book, we create and use classes that handle monetary amounts precisely.