5.6 Application: Compound-Interest Calculations

Let’s use the for statement to compute compound interest. Consider the following problem:

  • A person invests $1,000 in a savings account yielding 5% interest. Assuming that all the 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

    • a is the amount on deposit at the end of the nth year.

The solution to this problem (Fig. 5.6) involves a loop that performs the indicated calculation for each of the 10 years the money remains on deposit. For this solution, we use double values for the monetary calculations, then we discuss the problems with using floating-point types to represent monetary amounts. In the next section, we’ll develop a new DollarAmount class that uses very large integers to precisely represent monetary amounts. As you’ll see, the class performs monetary calculations using only integer arithmetic.

Fig. 5.6 Compound-interest calculations with for.

Alternate View

 1   // Fig. 5.6: Interest.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 << endl;
16      cout << "    Interest rate:    " << rate << endl;
17
18      // display headers
19      cout << "
Year" << setw(20) << "Amount on deposit" << endl;
20
21      // calculate amount on deposit for each of ten years              
22      for (unsigned 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 << endl;         
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

Lines 12–13 in main declare double variables principal and rate, and initialize principal to 1000.00 and rate to 0.05. C++ treats floating-point literals like 1000.00 and 0.05 as type double. Similarly, C++ treats whole-number literals like 7 and -22 as type int. Lines 15–16 display the initial principal and the interest rate.

Formatting with Field Widths and Justification

The output statement in line 10 before the for loop and the output statement in line 27 in the for loop combine to print the values of the variables year and amount with the formatting specified by 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 is less than four character positions wide, the value is right justified in the field by default. If the value to be output is more than four character positions wide, the field width is extended with additional character positions to the right to accommodate the entire value. To indicate that values should be output left justified, simply output nonparameterized stream manipulator left (found in header <iostream>). Right justification can be restored by outputting nonparameterized stream manipulator right.

The other formatting in the output statements indicates that variable amount is printed as a fixed-point value with a decimal point (specified in line 10 with the stream manipulator fixed) right justified in a field of 20 character positions (specified in line 27 with setw(20)) and two digits of precision to the right of the decimal point (specified in line 10 with manipulator setprecision(2)). We applied the stream manipulators fixed and setprecision to the output stream cout before the for loop because these format settings remain in effect until they’re changed—such settings are called sticky settings 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. We discuss C++’s powerful input/ output formatting capabilities in Chapter 13, Stream Input/Output: A Deeper Look.

Performing the Interest Calculations with Standard Library Function pow

The for statement (lines 22–28) executes its body 10 times, varying the unsigned int control variable year from 1 to 10 in increments of 1. This loop terminates when year becomes 11. 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>. 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.

The body of the for statement contains the calculation 1.0 + rate as pow’s first argument. This calculation produces the same result each time through the loop, so repeating it in every iteration of the loop is wasteful.

Performance Tip 5.1

In loops, avoid calculations for which the result never changes—such calculations should typically be placed before the loop. Many of today’s sophisticated optimizing compilers will place such calculations before loops in the compiled code.

Floating-Point Number Precision and Memory Requirements

Variables of type float represent single-precision floating-point numbers and have approximately seven significant digits on most of today’s systems. Variables of type double represent double-precision floating-point numbers. These require twice as much memory as float variables and provide approximately 15 significant digits on most of today’s systems—approximately double the precision of float variables. Most programmers represent floating-point numbers with type double. In fact, C++ treats all floating-point numbers you type in a program’s source code (such as 7.33 and 0.0975) as double values by default. Such values in the source code are known as floating-point literals. See Appendix C for the fundamental types’ value ranges.

Floating-Point Numbers Are Approximations

In conventional arithmetic, floating-point numbers often arise as a result of division—when we divide 10 by 3, the result is 3.3333333…, with the sequence of 3s repeating infinitely. The computer allocates only a fixed amount of space to hold such a value, so clearly the stored floating-point value can be only an approximation. As you can see, double suffers from what we call representational error.

Common Programming Error 5.6

Using floating-point numbers in a manner that assumes they’re represented exactly (e.g., using them in comparisons for equality) can lead to incorrect results. Floating-point numbers are represented only approximately.

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 may actually be 98.5999473210643. Calling this number simply 98.6 is fine for most applications involving body temperatures. Due to the imprecise nature of floating-point numbers, type double is preferred over type float, because double variables can represent floating-point numbers more precisely. For this reason, we use type double throughout the book.

A Warning about Displaying Rounded Values

We declared variables amount, principal and rate to be of type double in this example. We’re dealing with fractional parts of dollars and thus need a type that allows decimal points in its values. Unfortunately, floating-point numbers can cause trouble. Here’s a simple explanation of what can go wrong when using double (or float) to represent dollar amounts (assuming that dollar amounts are displayed with two digits to the right of the decimal point): Two calculated double dollar amounts stored in the machine could be 14.234 (which would normally be rounded to 14.23 for display purposes) and 18.673 (which would normally be rounded to 18.67 for display purposes). When these amounts are added, they produce the internal sum 32.907, which would normally be rounded to 32.91 for display purposes. Thus, your output could appear as

14.23+ 18.67¯32.91

but a person adding the individual numbers as displayed would expect the sum to be 32.90. You’ve been warned!

Error-Prevention Tip 5.6

Do not use variables of type double (or float) to perform precise monetary calculations. The imprecision of floating-point numbers can lead to errors.

Even Common Dollar Amounts Can Have Representational Error in Floating Point

Even simple dollar amounts, such as those you might see on a grocery or restaurant bill, can have representational errors when they’re stored as doubles. To see this, we created a simple program with the declaration


double d = 123.02;

then displayed variable d’s value with many digits of precision to the right of the decimal point—we ask you to do this in Exercise 5.36. 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 double, many cannot. In the next section, we’ll build a class that represents and processes dollar amounts using only integer arithmetic. This eliminates the representational errors associated with double values, because integers are represented exactly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset