CS 16, Winter 2018

Lab03:
Functions


Goals for this lab

By the time you have completed this lab, you should be able to

Step by Step Instructions

Step 1: Get together with your lab partner, and create a lab03 directory

By now you should know the drill: Choose who will be the first pilot and who will start as navigator, and then remember to switch (at least once) during the lab. But you should probably know the long-term goal too:

Each partner should participate in both roles in approximately equal parts over the course of the quarter. We realize it is not possible to equally split time in every lab, but it's worth trying, and it is possible to make up for unequal splits in future labs. We trust you will try to meet this goal. Thanks!

If your assigned partner is more than 5 minutes late, ask the TA to pair you with someone else for this week.

This lab's first pilot should log in, create ~/cs16/lab03/ and make that your current directory.

Step 2: Practice writing and testing small functions at the ch prompt

Start ch, and simplify the ch prompt if you want:

-bash-4.3$ ch
                              Ch (64-bit)
                Professional edition, version 7.5.3.15401 
              Copyright (C) SoftIntegration, Inc. 2001-2016
                     http://www.softintegration.com
/cs/class/cs16/lab03> _prompt = "ch> "
ch>
ch>

Type (or copy/paste) the function below, int f1(int value), all on one line at the ch prompt. In order to spread the definition over more than one line in ch, it is necessary to type a continuation character (the backslash, '\') at the end of all but the last line:

int f1(int value) \
{ \
   return value * value; \
}
In this case, the function is short enough that it could have been written on one line, and then it would not require the continuation characters.By the way, here is the function described in words like the instructions below for functions that you will create yourself:

Write a function named f1 that takes one int argument named value, and has a return type of int. It should return the squared value.

Then test it. Here is how it should look:
ch> int f1(int value) \
ch> { \
ch>    return value * value; \
ch> }
ch> f1(4)
16

If you made a mistake or want to change something, you can't just redefine the function in the same ch session. Instead exit ch, and start over.

Now it's your turn to write one.

Write a function (either all on one line, or using the continuation character) named f2 that takes one int argument named x, and returns a double value equal to 1.0/x (the multiplicative inverse of x). Do NOT print anything. Type your function definition at the ch prompt. Then test it a few times:
ch> CENSORED: FUNCTION DEFINITION HERE
ch> f2(100)
0.0100
ch> f2(0)
inf
ch> double answer = f2(25);
ch> answer
0.0400
ch>

Notice in the last test above, how the function returns an answer without printing anything - in this test, the answer is stored in a variable and shown later. Also notice the special value ch printed when the function tried to calculate 1.0/0 and keep this behavior in mind.

Step 3: Write and test a longer function with a ch "function file"

If you create a file with .chf as the extension, and the first part of this file's name exactly matches the name of the function (to be used externally), and the file is stored in the current directory (or elsewhere in _fpath), then you can execute the function at the ch prompt.

Use emacs or another editor to create a file named dfactorial.chf. [Note you don't have to exit ch to start the editor.] Type a comment such as (// calculates factorial of n as double) on the first line. Then define a function to find n factorial as a double value. In case you never heard of it, or you forgot its definition, n factorial is abbreviated as n! and it is defined as follows:

n! = (n)(n-1)...(2)(1)

where n is a non-negative integer, and 0! = 1. So, for example:

5! = 5*4*3*2*1 = 120

Type the function definition after the comment. Here are the specific instructions:

Write a function named dfactorial that takes one int argument named n, and returns a double value that is equal to n factorial.

Save the file as dfactorial.chf in the lab03 directory.

Then test it from the ch prompt. If something doesn't work correctly, then fix the problem before going to Step 4. Here are some correct answers to expect:

ch> dfactorial(5)
120.0000
ch> dfactorial(10)
3628800.0000
ch> dfactorial(50)
30414093201813375576366966406747986832057064836514787179557289984.0000

Step 4: Find out your function's limits

First: switch roles between pilot and navigator if you did not already do that.

Of course you noticed that 50! is a very large number, but apparently it still is within the range of the double data type. What value results when you plug in 200 for n? Now we want you to experiment a bit.

  1. Devise a way to find out the largest value of n for which dfactorial(n) returns an accurate value.
  2. Find this largest value, and remember it to use for Step 5 (also to tell your TA if they ask later).

Step 5: Write and test a program to approximate e

Here, e refers to the mathematical constant that is the base of natural logarithms. Like π and other such constants, this number is irrational, and so it can only be approximated (2.71828183 is a usable approximation, but nevermind that for now).

One way to define the true value of e is by the sum of an infinite series of multiplicative inverses of factorials:

Recall that 0! is 1, so this series begins with 1 + 1, its third term is 1/2! (= 1/2), its fourth term is 1/3! (= 1/6), and so on. Of course you can't write a program to calculate an infinite series, and besides that you know your factorial function has a largest value for which it works correctly.

Write a C++ program that contains a copy of your dfactorial function, and a new main function that uses it to approximate and print the value of e. First exit ch, then accomplish the following steps:

  1. Make a copy of dfactorial.chf named e.cpp:
    -bash-4.3$ cp dfactorial.chf e.cpp
  2. Edit the copy with emacs or another editor:
    -bash-4.3$ emacs e.cpp
  3. Type a comment at the top of the file - above the dfactorial function - with a very brief description of the program you are creating, plus your name(s) and the date.
  4. Type a blank line after the comment. Then type the usual directives to include the C++ input-output stream library and make the std namespace available, and then another blank line - all above the existing function.
  5. Now skip down to below the dfactorial function, and begin the main function as usual. You might as well terminate main now too, and include the following features inside its brackets (curly braces):
    1. Declare a double variable named e, and initialize it to 1. Also declare an integer variable named n which will be used for loop control, and for passing to dfactorial.
    2. Begin a loop in which the value of n will vary from 1 to the maximum value that can be passed to your dfactorial function (see Step 4 above).
    3. Inside the body of the loop, use the variable e to accumulate the sum of terms necessary to approximate e (i.e., add 1/n! to the current value of e on each iteration).
    4. After the loop, print the value of e with 8 digits of precision after the decimal point, and with a nice label, as in the example run below from our solution.
    5. As a reminder, in order to print the value with 8 digits after the decimal, type these lines before using cout to print the number:
      cout.setf(ios::fixed);
      cout.setf(ios::showpoint);
      cout.precision(8);
    6. Exit normally.

Make an executable version of the program, and test it before submitting in the next step:

-bash-4.3$ make e
g++     e.cpp   -o e
-bash-4.3$ ./e
e is approximately 2.71828183

Step 6: Submit your program

If you are still logged on, and your current directory is still the same as your program, then the quickest way to submit is by entering the following command (suggest you copy/paste):

~submit/submit -p 947 e.cpp
Otherwise you can use the submit.cs interface at https://submit.cs.ucsb.edu/ from your web browser. Either way, be sure to wait for the results of the only test. Fix any problems, and resubmit as necessary until your score is 50/50 points.

If you are working with a partner, be sure that both partners' names are in a comment at the top of the source code file, and be sure to properly form a group for this project in the submit.cs system.


Evaluation and Grading

Each student must accomplish the following to earn full credit [50 total points] for this lab:

If you finish before the end of your lab period, work on the optional challenges below.


Optional Extra Challenges


Prepared by Michael Costanzo.