CHAPTER 4

Questions

1. A procedure is a unit of code designed to perform a sub-task of some main task. Its code is written out only once in some module. It is better to use a procedure when you have to perform a sub-task more than once.

2. First type: no data used or produced.
Second type: data used but none produced.
Third type: data produced only.
Fourth type: data used and produced.

3. Invocation of a procedure is the occurrence of its name somewhere in a program. The invocation instructs the processor to execute the code of the procedure.

4. A procedure that calls itself is recursive. Recursion should be used when the original problem is naturally recursive.

5. When procedure value parameters are declared, say PROCEDURE Write (ch : CHAR), a memory location is set aside for that parameter by the compiler. When the procedure is called, Write (somevar), the parameter is copied into the memory location set aside for that particular procedure, creating a new and independent copy of the value. In using variable parameters, for example, the one in PROCEDURE Read (VAR ch : CHAR), the parameter name is attached to the same memory location as that named by the actual parameter at the time the call is made. These constitute one memory location for that parameter so that changes using the local name are automatically reflected in the global one. The actual parameter must be a variable. A variable parameter can be differentiated from a value parameter by the VAR heading declared before a parameter.

6. This is true because INTEGERs are assignment compatible with CARDINALs, as long as they are in the same range. When WriteCard is called with an INTEGER as its parameter, it will assign that parameter to the memory location because of their compatibility. However, using ReadCard with an INTEGER is forbidden because of expression compatibility concerns. Because ReadCard is a variable parameter, it tries to couple the INTEGER parameter to a CARDINAL memory location, which is forbidden. That is why the actual type must exactly match the formal type of a variable parameter.

7. A function procedure returns a type, the name of the returned type being placed after the closing parenthesis of the formal parameter list. A specific RETURN [value] statement has to be executed somewhere in the body of the function procedure. When calling a function procedure, a parameter list has to be included even if it is empty. Finally a call to a function procedure, has to be in a form of an expression rather than just a command line (ie. x := SomeProc() rather than SomeProc()).

8. RETURN [value] returns the value of the specified type from a function procedure. A bare RETURN in a proper procedure terminates the action prematurely, returning to the caller.

9. ABS: a built-in function procedure.
FLOAT: a built-in function procedure.
ReadReal: an imported proper procedure.
MAX: a built-in function procedure.
ReadResult an imported function procedure.
Read: an imported proper procedure.
CAP : a built-in function procedure.
MIN : a built-in function procedure.
exp : imported function procedure.
ln : imported procedure.

10. Each recursive call of Fac has to supply a new and independent value to start the next code cycle. This can only be done with value parameters. A variable parameter would modify all the data held in each of the recursive calls.

11. In simple interest, the interest rate is applied to only the original principal amount when computing interest. In compound interest, the rate is applied to both the original principal and whatever interest has accumulated.

12. The net present value is the amount equal to a series of future payments. The net future value is the predicted value of what the principal will eventually become.

13. When one makes mortgage payments against a debt, one is paying off the present value by a series of future payments. When one receives an annuity, the present value of a deposit is being paid out by a series of future payments. The only difference between the two is the direction the money goes; the computation is identical.

Problems

Note: Not all problems are shown. Most problems are left up to students as labs.

(* modified
   June 11 1999
   Chapter 4 Question 15
   ERROR TRAPPING INCLUDED  *)

MODULE Areas;

(* Written by R.J. Sutcliffe *)
(* to illustrate procedures *)
(* using P1 Modula-2 for the Macintosh computer *)
(* last revision 1993 02 25 *)

FROM STextIO IMPORT
  WriteString, ReadChar, WriteLn, SkipLine;
FROM SRealIO IMPORT
  WriteFixed, ReadReal;
FROM RealMath IMPORT
  sqrt;
FROM SIOResult IMPORT
  ReadResult, ReadResults;

VAR
  dimension, height, mArea, mPerim : REAL;
  which, ans : CHAR;
  again : BOOLEAN;

(*********************************************)
PROCEDURE GetNum (VAR theNum : REAL);
VAR
  readOK : BOOLEAN;

BEGIN
  REPEAT
    WriteString ("Type the number here ==> ");
    ReadReal (theNum);
    readOK := (ReadResult() = allRight);
    IF NOT readOK
      THEN
        WriteLn;
        WriteString ("error in input number; try again.");
        WriteLn;
      END;
    SkipLine;
  UNTIL readOK;
END GetNum;

PROCEDURE CalcSquare (side : REAL; VAR area, perim: REAL);

BEGIN
  area := side * side;
  perim := 4.0 * side;
END CalcSquare;

PROCEDURE CalcCircle (radius : REAL; VAR area, perim: REAL);

CONST
  pi = 3.141592653;
  twopi = 2.0 * pi;

BEGIN
  area :=pi * radius * radius;
  perim := twopi * radius;
END CalcCircle;

PROCEDURE CalcTri (height : REAL; base : REAL; VAR area, perim : REAL);

PROCEDURE hypot (a : REAL; b : REAL) : REAL;

VAR
  c : REAL;

BEGIN
  c := a * a + b * b;
  RETURN sqrt(c);
END hypot;

BEGIN
  area := 0.5 * base * height;
  perim := base + 2.0 * (hypot(0.5 * base, height));
END CalcTri;

PROCEDURE CalcRect (height : REAL; base : REAL; VAR area, perim : REAL );
BEGIN
  area := base * height;
  perim := 2.0 * base + 2.0 * height;
END CalcRect;

(*************************************************)

BEGIN    (* main program *)
  WriteString ("This program calculates areas and perimeters of");
  WriteLn;
  WriteString ("squares from a side length ");
  WriteString ("or circles from the radius.");
  REPEAT
    WriteLn;
    (* Present menu, give user the choice. *)
    WriteString ("Do you want to work with ");
    WriteString ("a circle or a square? ");
    WriteLn;
    WriteString ('Type a "C", "R", "S", or "T" here ===> ');
    ReadChar (which);
    SkipLine;
    which := CAP ( which);
    WriteLn;
    again := TRUE;

    (* now obtain a set of data *)
    IF (which = 'C') OR (which = 'S')
      THEN
        WriteString ("What is the dimension of the figure ?");
        WriteLn;
        GetNum (dimension);
      ELSIF (which = 'R') OR (which = 'T') THEN
        WriteString ("What is the height?"); WriteLn;
	GetNum (height);
	WriteString ("What is the base?"); WriteLn;
	GetNum (dimension);
      ELSE
        WriteString ("Not an option...quitting"); WriteLn;
	again := FALSE;
      END;

    (* Do only if correct option selected *)
    IF again
      THEN

        IF which = 'C'
          THEN    (* Now go do one. "S" is the default *)
            CalcCircle (dimension, mArea, mPerim);
          ELSIF which = "R" THEN
      	    CalcRect (height, dimension, mArea, mPerim);
          ELSIF which = "S" THEN
            CalcSquare (dimension, mArea, mPerim);
	  ELSE
	    CalcTri (height, dimension, mArea, mPerim);
          END;    (* if *)

        WriteString ("The area is ");
        WriteFixed (mArea, 2, 0);
        WriteString (" square units and ");
        WriteLn;
        WriteString ("the perimeter is ");
        WriteFixed (mPerim, 2, 0);
        WriteString (" units.");
        WriteLn;
        WriteLn;
      END;

      WriteString ("Do another (Y/N) ==>");
      ReadChar (ans);
      SkipLine;
      again := (CAP (ans) = "Y");
  UNTIL NOT again;
END Areas.
(*	Translated into ISO Modula-2
        June.11.1999
	Chapter 4 Question 27
	ERROR TRAPPING INCLUDED	*)


MODULE Change;

FROM STextIO IMPORT
   WriteString, WriteLn, ReadChar, SkipLine;
FROM SWholeIO IMPORT
   WriteCard, ReadCard;
FROM SIOResult IMPORT
   ReadResult, ReadResults;

PROCEDURE CoinChange (VAR amountLeft : CARDINAL; value : CARDINAL);
(* Calculates the number of coins of the given value *)

VAR
   numberOfCoins : CARDINAL;

BEGIN
   numberOfCoins := amountLeft DIV value;
   amountLeft := amountLeft MOD value;
   WriteCard (numberOfCoins, 0);
   WriteLn;
END CoinChange;

(* main program *)

VAR
   count, total, leftover, cost, coinValue : CARDINAL;
   again : CHAR;
   ok : BOOLEAN;

BEGIN
   WriteString ("This program will dispense change for a dollar for some");
   WriteLn;
   WriteString ("purchased item costing less than a dollar.");
   WriteLn; WriteLn; WriteLn;

   REPEAT   (* give the option to redo program *)

      (* initalize vars *)
      total := 0;
      REPEAT   (* keep getting till their done giving *)

        REPEAT   (* make sure that all are correct types *)
          cost := 0;
          WriteString ("Enter the cost of the item (in cents please): ");
          WriteLn;
          ReadCard (cost);
          ok := ReadResult() = allRight;
          SkipLine;
       UNTIL ok;

       total := cost + total;
      UNTIL (cost = 0) OR (total > 100);

      (* amount was greater than 100 *)
      IF total > 100 THEN
         WriteString ("Sorry, you've exceeded the limit.");
         WriteLn;
      ELSE
        leftover := 100 - total;
        WriteLn; WriteLn;

        FOR count := 1 TO 4 DO   (* 4 types of coins, so a loop till 4 *)
          WriteString ("The number of  ");

          IF count = 1 THEN
            WriteString ("quarter ");
            coinValue := 25;
          ELSIF count = 2 THEN
            WriteString ("dimes ");
            coinValue := 10;
          ELSIF count = 3 THEN
            WriteString ("nickels ");
            coinValue := 5;
          ELSE
            WriteString ("pennies ");
            coinValue := 1;
         END;

         WriteString ("is: ");
         CoinChange (leftover, coinValue);
         WriteLn;
       END;   (* end FOR *)

     END;   (* end IF *)

    WriteLn; WriteLn;
    WriteString ("Do you want to go again (Y/N)? ");
    ReadChar (again);
    SkipLine;
    WriteLn; WriteLn; WriteLn;
   UNTIL CAP (again) # 'Y';

  WriteString ("See you around... ");
  WriteLn;
END Change.