Problem: You have a bank account whose annual interest rate depends on the amount of money you have in your account at the beginning of each year. Your annual rate starts at 3%, and grows by an additional half a percent for each thousand dollars in your account up to, but not exceeding 8%. So, for example, if you have $3,358.02 in your account at the beginning of the year, your rate is 4.5%. Interest in this account is compounded monthly at the annual rate (i.e. the monthly compounding rate is the annual rate divided by 12). Each year you also make a trasaction (deposit or withdrawal) before the bank figures out what your rate is (fortunately!). Write a program that simulates 5 years under this system, interactively querying the user for transactions at the beginning of each year, and returning the balance at the end of the 5th year.
There's a lot to this problem. However, imagine how much easier it would be to solve if the following functions were available:
double transaction(double B); - which would
do the interactive
part for you - taking the initial balance B and
returning the balance after the transaction.
double rate(double B); - which would return
the interest
rate based on the account balance.
double compound(double r); - which would give
you the value of
a single dollar after a year's monthly compounding with annual
interest rate r. If your blance is
B and your rate is r at the
beginning of the year, the new balance is
B*compound(r).
double B = 0.0;
for(int i = 0; i < 5; i++)
{
B = transaction(B);
double r = rate(B);
B = B*compound(r);
}
cout << B << endl;
This is a pretty easy program! Of course, the 3 functions in our
wish list do not exist, so we'll have to implement them for
ourselves.
double transaction(double B)
{
// Get type of transaction
char act;
cout << "Enter w: withdrawl d:deposit ";
cin >> act;
// Get amount of transaction
double A;
cout << "Enter amount: ";
cin >> A;
// Get new Balance figure
if (act == 'w')
B = B - A;
else
B = B + A;
return B;
}
|
double rate(double B)
{
// Get # of thousands
int T = B/1000;
// Calc rate
double r = 3 + T*0.5;
if (r > 8)
r = 8;
return r;
}
|
double compound(double r)
{
// Sim. year with monthly compounding
double R = r/100, total = 1.0;
for(int i = 0; i < 12; i++)
total = total*(1 + R/12);
return total;
}
|
transaction, I
don't need to worry about any other aspect of the program - it's
like transaction is its own little (easy!) program
to write. Take a look at the complete program.
cmath
library, the pow function. Specifying multiple
parameters for a function is just like spcifying several single
parameters in a comma-separated list. For example, suppose you
wanted to define a function max that looked at two
ints and returned the larger of the two. It's
prototype would be
int max(int,int);The definition would look like this:
int max(int a, int b)
{
if (a < b)
return b;
else
return a;
}
Note that this example shows you that you can return from anywhere
within a function, just like you can return from anywhere within
main.
It's important to note that the order of arguments is matters. For example, suppose you had a function
void rep(int,char);that printed the
char argument to the screen the
number of times given by the int. If I want to print
a # symbol 42 times, I need to be sure to say
rep(42,'#'), because the function expects the
int object first. If I said rep('#',42)
instead, do you know what'd happen? I'd print 35 *s!
Why? Because the same kind of implicit type conversions that go
on inside expressions go on with function arguments! The
rep function expects an int as its first
argument, and when it gets '#' instead, it simply
converts it to an int ... and the ASCII value of
'#' is 35, so that's the int you get.
Likewise, a char is expected as the second argument,
and when rep gets the number 42 instead, it converts
it to a character, and ASCII value 42 gives you the
char '*'.
When implicit conversions aren't possible, the compiler gives
you an error message. For example, if you tried to call
rep("#",42) the compiler would give you an error
saying that the first argument of rep was supposed
to be an int, but you gave it a
string, and there's no way to convert the
string to an int. You'll likely see
lots of these messages in your life!
bool are
traditionally referred to as predicates. Imagine
that you had to compute more and more terms of a series
approximation for
cos(x) until your series approximation and the
cmath library approximation agreed to a particular
precision. In other words, you had two floating-point values and
a number n and you had to test to see whether they
agreed to within 10-n. We could define a
function approxequal to do this.
bool approxequal(double, double, int);... where the first two arguments are the quantities to compare, and the
int argument is the precision.
bool approxequal(double x, double y, int n)
{
if (fabs(x - y) > pow(10,-n))
return false;
else
return true;
}
With the definition of this predicate, the main
while-loop of you program would look like
while(!approxequal(series,libvalue,n))
{
...
Really there's no need to bring predicates up as a special
subject, since functions that return bools are not
any more special than functions that return, say,
strings. However, you might not have thought much
about the use of having such functions.