CPSC 124, Winter 1998

First Test

This is the first test given in CPSC 124: Introductory Programming, Winter 1998. See the information page for that course for more information.

The answers given here are sample answers that would receive full credit. However, they are not necessarily the only correct answers.

Question 1: Define the following terms, as they relate to this course:

a) compiler

Answer: A compiler is a program that can translate programs written in a high-level language into machine language. This is necessary because computers cannot directly execute high-level-language programs. (In the case of Java, the compiler translates Java programs into Java bytecode, which is the machine language for a "virtual machine." A real computer can run a Java bytecode interpreter to execute Java bytecode programs.)

b) type (of a variable)

Answer: The type of a variable specifies the set of values that can be stored in the variable. For example, a variable of type int can only hold whole numbers in the range from -231 to 231-1. A variable of type double, on the other hand, can store real numbers (containing decimal points).

c) algorithm

Answer: An algorithm is an unambiguous, step-by-step procedure for performing some task, which is guaranteed to terminate after a finite number of steps.

d) dummy parameter

Answer: Parameters are used for communication between a subroutine and the rest of the program. When the subroutine is written, dummy parameters are used as place-holders to represent the actual parameters that will be provided when the subroutine is called. For example, in the subroutine that begins: "static stars(int numberOfStars)...", numberOfStars is a dummy parameter.

Question 2: There are two basic approaches to program design: top-down design and bottom-up design. Explain what is meant by these two terms and how each approach can be used to help in the design of complex programs.

Answer: The general idea is that a large problem can be broken down into smaller problems, which can themselves be broken down into smaller problems, and so on until the problems on the bottom level are ones for which solutions are known or easy to figure out. The problems form a hierarchy with the main problem at the top and the basic problems at the bottom. The question is, where does a programmer start working? In top-down design, the programmer starts by considering the main problem and how to break it up into smaller, more manageable sub-problems. In bottom-up design, the programmer starts by programming solutions to smaller problems and then combines them to solve larger problems.

Step-wise refinement is a type of top-down design in which the programmer starts with an overall outline of the program, and then expands on it by gradually filling in details. Object-oriented programming tends to be more bottom-up: The programmer designs objects that can be combined to make a complete program.

Question 3: Recall that rolling a die can be simulated with the command

die = (int)(6 * Math.random()) + 1;

Why does this work? What is Math.random()? Why is it multiplied by 6? What is the effect the (int) and why is it necessary?

Answer: Math.random() is a built-in method in Java. Each time it is called, it returns a random real number that is >= 0.0 and < 1.0. Multiplying the random number by 6 gives a number that is >= 0.0 and strictly < 6.0. Since the number on a die is an integer, it is necessary to throw away the fractional part of the number. This is done by the "type cast" operation, (int), which takes a real number and turns it into an integer by dropping any digits that follow the decimal point. In this case, the result is one of the integers 0, 1, 2, 3, 4, or 5. Finally, adding 1 gives an integer in the range 1 to 6, which is just what is needed to represent the roll of a die.

Question 4: Suppose that income tax is determined as follows: If income is less than $10,000, then there is no tax. For incomes between $10,000 and $30,000, the tax is 0.15 times (income - 10000). For incomes greater than $30,000, the tax is 3000 plus 0.3 times (income - 30000). Write a program segment that inputs the amount of income from the user and prints out the income tax on that amount. You do not have to write a complete program, but you should declare any variables that you use.

Answer: There are, of course, several ways to do this. Here is one example:

          double income;  // amount of income, to be input by the user
          double tax;     // amount of tax on the specified income
          console.put("Please enter your income: ");
          income = console.getlnDouble();
          if (income < 10000) {
             console.putln("There is no tax on an income of $" + income);
          else if (income < 30000) {
             tax = 0.15 * (income - 10000);
             console.putln("The tax on $" + income + " is $" + tax);
          else {
             tax = 3000 + 0.3 * (income - 30000);
             console.putln("The tax on $" + income + " is $" + tax);

Question 5: Write a program segment that simulates rolling a pair of dice over and over until a pair of threes is rolled (that is, until the number on each die is equal to 3). The program should count the number of rolls and output this number at the end. You do not have to write a complete program, but you should declare any variables that you use. (The formula for rolling a die is given in problem 3.)

Answer: Here are two possible answers. Note that "die1 == 3 && die2 == 3" is the condition for ending the loop, since it says that both dice show 3. The condition for continuing the loop is the opposite of this, "die1 != 3 || die2 != 3".

   Version 1:

          int die1, die2;  // values showing on dice
          int rollCt = 0;  // number of times dice have been rolled
          while (true) {
             die1 = (int)(6 * Math.random()) + 1;
             die2 = (int)(6 * Math.random()) + 1;
             if (die1 == 3 && die2 == 3)
          console.putln("Number of rolls = " + rollCt);

   Version 2:

          int die1 = 0;   // values on dice; initial values of zero
          int die2 = 0;   //     are required to make the while loop
                          //     execute the first time
          int rollCt = 0; // number of times dice have been rolled
          while (die1 != 3 || die2 != 3) {
             die1 = (int)(6 * Math.random()) + 1;
             die2 = (int)(6 * Math.random()) + 1;
          console.putln("Number of rolls = " + rollCt);

Question 6: a) Write a subroutine named "stars" that will output a line of stars to a console. (A star is the character "*".) The number of stars should be given as a parameter to the subroutine. Use a for loop. For example, the command "stars(20)" would output


b) Now write a for statement that will output 10 lines of stars with 1 star in the first line, 2 stars in the second line, and so on, as shown below. Call the subroutine you wrote in part a) to output each line of stars.


Answer: Assume that console is a static variable of type Console. The subroutine for part a) could be written as follows.

            static void stars(int numberOfStars) {
                 // output a line containing the specified number of stars
               for (int i = 0; i < numberOfStars; i++) {
               console.putln();  // output carriage return after the *'s

For part b), the main program could use the following for loop to produce the ten lines of stars:

             for (lineNum = 1; lineNum <= 10; lineNum++)

Question 7: Show the exact output produced by the following Java program. (Explain your work, to get partial credit.)

              public class TestQuestion {
                public static void main(String[] args) {
                   Console console = new Console();
                   int a, b, c;
                   a = 30;
                   b = 2;
                   c = 0;
                   while ( a > b ) {
                      console.putln("b is " + b);
                      b = (a + b) / 2;
                   console.putln("c is " + c);

Answer: The exact output of the program consists of the following lines written to the console:

             b is 2
             b is 16
             b is 22
             b is 25
             c is 4

Each time through the while loop, the current value of b is output by the first line in the loop. The first time through, the value of b is 2. The value of b then changes to (a+b)/2, which is (30+2)/2, or 16. The value of c changes to 1, and the value of a changes to 29.

The second time through the loop, the value of b that is output to the console is 16. Then the value changes to (a+b)/2, which is now (29+16)/2, or 45/2, or 22. Note that the answer is 22, not 22.5, because when two integers are divided in Java, the result is defined to be an integer. Essentially, the fractional part is thrown away. In this iteration of the loop, c changes to 2 and a changes to 28.

This continues for two more steps, outputting 22 and 25 as the values of b. At this point, b becomes 26, c becomes 4, and a becomes 26. Since a is no longer > b, the loop ends and the final value of c is output.

Question 8: Explain what is meant by good programming "style" and explain why it is important. Give several rules of good programming, with a short justification of each rule.

Answer: Programs are written for two audiences: for the computer and for human readers. The computer doesn't care about anything except the formal rules of syntax. However, for human readers, programs should be written with style. This makes the programs easier to read and understand, and that in turn makes it easier to get a program right in the first place and to update the program or correct errors when they turn up later.

For example, variables and methods should always be given meaningful names, so that the reader can more easily understand how they are being used in the program. Indentation should be used to make the structure of the program easy to see. For example, it is important to be able to easily determine exactly which statements are inside a loop. Since it is not always easy to tell the meaning of a program just by reading the code, comments should be used to explain what the program is for and any limitations it might have. They should be also be used to explain the logic of the program whenever it is not obvious just from reading the program itself.

Question 9: A subroutine is said to have a contract What is meant by the contract of a subroutine? When you want to use a subroutine, why is it important to understand its contract? The contract has both "syntactic" and "semantic" aspects. What is the syntactic aspect? What is the semantic aspect?

Answer: The contract of a subroutine says what must be done to call the subroutine correctly and what it will do when it is called. It is, in short, everything a programmer needs to know about the subroutine in order to use it correctly. (It does not include the "insides," or implementation, of the subroutine.)

Correctness has two components: Syntactic and semantic. The syntactic component of a subroutine's contract includes the name of the subroutine, the number of parameters, and the type of each parameter. This is the information needed to write a subroutine call statement that can be successfully compiled. The semantic component of the contract specifies the meaning of the subroutine, that is, the task that the subroutine performs. It might also specify limitations on what parameter values the subroutine can process correctly. The semantic component is not part of the program. It is generally expressed in comments.

Question 10: Java has become an important programming language in a very short time. What are some of the things that have made it so popular? (Your answer should include, but not be limited to, a discussion of Java's role on the Internet.)

Answer: Java is a multiplatform language. That is, programs written in Java can be run on many different types of computer. This is essential for programs that are going to be downloaded over the Internet, since many types of computer are connected to the Net. It allows Java applets to be used on Web pages, and Java gets a lot of its popularity from its association with the Web.

Java also has many features that make it a good choice for modern computing. It is object-oriented. It supports multithreading, making it easy to write programs that do several things at once. It uses garbage collection for memory management, which frees the programmer from worrying about one of the most common sources of errors in programs. It has built-in support for a graphical user interface and event-driven programming.

David Eck 30 January 1998