# Class 17: Functions II

Sections 4.4-4.5 of Problem Solving with C++

Lecture

## Functions and Top-Down design

The essence of programming is breaking down a single, large, complex problem into many simple pieces that can be attacked independently. Functions help us to do this, and that is one of their most important features. They help us write programs in a top down manner, essentially be letting us write our program using a "wish-list" of functions that we can actually go back and implement later. An example should make this clearer.

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 transaction (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 balance is `B` and your rate is `r` at the beginning of the year, the new balance is `B*compound(r)`.

With this "wish list" of functions, we could write the program quite easily:

`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;``}`

The key here is that each of these functions can be implemented independently. When I implement `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.

## Multi-Parameter Functions

Functions get infinitely more interesting when they have more than one argument or parameter. We've already seen at least one example of a multi-parameter function from the `cmath` library, the `pow` function. Specifying multiple parameters for a function is just like specifying several single parameters in a comma-separated list. For example, suppose you wanted to define a function `max` that looked at two `int`s 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 important. 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 `character` `'*'`.

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!

## Predicates

Functions which return the type `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 `bool`s are not any more special than functions that return, say, `string`s. However, you might not have thought much about the use of having such functions.

## Problems

1.     Surveying Problem This gives you another simple example of top-down design.

2.     Drawing a triangle with *'s This is a simple multi-parameter function problem.

3.     Distance between points This is another simple multi-parameter function problem.

4.     What percentage of numbers are prime? This is a simple example using a predicate.

Last modified by LT M. Johnson 08/16/2007 09:08 AM