Section 3.4
Return Values

A SUBROUTINE THAT RETURNS A VALUE is called a function. A given function can only return values of a specified type, called the return type of the function. A function call generally occurs in a position where the computer is expecting to find a value, such as the right side of an assignment statement, as an actual parameter in a subroutine call, or in the middle of some larger expression. A boolean-valued function can even be used as the test condition in an if, while, or do statement.

(It is also legal to use a function call as a stand-alone statement, just as if it were a regular subroutine. In this case, the computer ignores the value computed by the subroutine. Sometimes this makes sense. For example, the function console.getln(), with a return type of String, reads and returns a line of input typed in by the user. Usually, the line that is returned is assigned to a variable to be used later in the program, as in the statement "String name = console.getln();". However, this function is also useful in the subroutine call statement "console.getln();", which reads and discards all input up to and including the next carriage return.)

You've already seen how functions such as Math.sqrt() and console.getInt() can be used. What you haven't seen is how to write functions of your own. A function takes the same form as a regular subroutine, except that you have to specify the value that is to be returned by the subroutine. This is done with a return statement, which takes the form:

return expression;

Such a return statement can only occur inside the definition of a function, and the type of the expression must match the return type that was specified for the function. When the computer executes this return statement, it evaluates the expression, terminates execution of the function, and uses the value of the expression as the returned value of the function.

(Inside an ordinary method -- with declared return type "void" -- you can use a return statement with no expression to immediately terminate execution of the method and return control back to the point in the program from which the method was called. This can be a useful way to terminate execution of such a subroutine, but it is not required. In a function, on the other hand, a return statement, with expression, is required.)

Here is a very simple function that could be used in a program to compute 3N+1 sequences. Given one term in a 3N+1 sequence, this function computes the next term of the sequence:

        static int nextN(int currentN) {
           if (currentN % 2 == 1)     // test if current N is odd
              return 3*currentN + 1;  // if so, return this value
              return currentN / 2;    // if not, return this instead

Some people prefer to use a single return statement at the very end of the function. This allows the reader to find the return statement easily. We might choose to write nextN() like this, for example:

        static int nextN(int currentN) {
           int answer;  // answer will be the value returned
           if (currentN % 2 == 1)    // test if current N is odd
              answer = 3*currentN+1; // if so, this is the answer
              answer = currentN / 2; // if not, this is the answer
           return answer;   // (Don't forget to return the computed answer!)

Here is a subroutine that uses our nextN function. In this case, the improvement from the version in Section 3 is not great, but if nextN() were a long function that performed a complex computation, then it would make a lot of sense to hide that complexity inside a function:

         static void Print3NSequence(int startingValue) {
            // prints a 3N+1 sequence on the console, using
            // startingValue as the initial value of N

            int N = startingValue;  // N represents a term in the sequence
            int count = 1;   // count is the number of terms found
            console.putln("The 3N+1 sequence starting from " + N);
            console.putln(N);  // print initial term of sequence
            while (N > 1) {
                N = nextN(N);  // compute next term
                count++;   // count this term
                console.putln(N);  // print this term
            console.putln("There were " + count + " terms in the sequence.");
         }  // end of Print3NSequence()

Here are a few more examples of a functions. The first one computes a letter grade corresponding to a given numerical grade, on a typical grading scale:

       static char letterGrade(int numGrade) {
          // returns the letter grade corresponding to
          // the numerical grade numGrade
          if (numGrade >= 90)
             return 'A';   // 90 or above gets an A
          else if (numGrade >= 80)
             return 'B';   // 80 to 89 gets a B
          else if (numGrade >= 65)
             return 'C';   // 65 to 79 gets a C
          else if (numGrade >= 50)
             return 'D';   // 50 to 64 gets a D
             return 'F';   // anything else gets an F
       }  // end of function letterGrade()

The type of the return value of letterGrade() is char. Functions can return values of any type at all. Here's a function whose return value is of type boolean:

       static boolean isPrime(int N) {
          // returns true if N is a prime number, that is,
          // if N is a positive number that is not divisible
          // by any positive integers except itself and N
          int maxToTry = (int)Math.sqrt(N);
               // We will try to divide N by numbers between
               // 2 and maxToTry; If N is not evenly divisible
               // by any of these numbers, then N is prime.
               // (Note that since Math.sqrt(N) is defined to
               // return a value of type double, the value 
               // must be typecast to type int before it can
               // be assigned to maxToTry.)
           for (int divisor = 2; divisor <= maxToTry; divisor++) {
               if ( N % divisor == 0 )   // test if divisor evenly divides N
                  return false;  // if so, we know N is not prime
           // If we get to this point, N must be prime.  Otherwise,
           // the function would already have been terminated by
           // a return statement in the previous for loop.
           return true;  // yes, N is prime

        }  // end of function isPrime()

I'll finish this section with a complete new version of the 3N+1 program. This will give me a chance to show the function nextN() used in a complete program. I'll also take the opportunity to improve the program by getting it to print the terms of a sequence in columns, with several terms on each line. This will make the output more presentable. This idea is easy: Keep track of how many terms have been printed on the current line; when that number gets up to a certain value, start a new line of output. To make the terms line up into columns, I will use the version of console.put() with signature put(int,int). The second int parameter tells how wide the columns should be.

To demonstrate one more new idea, my program specifies the number of columns in the output and the width of the columns as constants. A constant is like a variable, except that its value can never be changed while the program is running. (To change the value, you would have to edit the program and recompile it.) Constants are used in programs because names are usually easier to read and understand than actual literal constants.

In Java, a constant is defined by using the modifier "final" on a variable declaration. The word final here indicates that the constant is in final form -- that the value that is assigned to it is final and cannot be changed. Later, you'll see that the modifier final can also be used on method definitions.

      public class ThreeN {
             A program that computes and displays several 3N+1
             sequences.  Starting values for the sequences are
             input by the user.  Terms in a sequence are printed
             in columns, with several terms on each line of output.
             After a sequence has been displayed, the number of
             terms in that sequence is reported to the user.
         final static int numberOfColumns = 5;  // constant specifying number
                                                // of terms on each output line
         final static int columnWidth = 8;  // constant specifying the width,
                                            // in number of characters, of each
                                            // column in the output
         static Console console;  // window for input/output

         public static void main(String[] args) {

            console = new Console();
            console.putln("This program will print out 3N+1 sequences");
            console.putln("for starting values that you specify.");
            int K = 0;
            do {
               console.putln("Enter a starting value;");
               console.put("To end the program, enter 0: ");
               K = console.getInt();  // get starting value from user
               if (K > 0)   // print sequence, but only if K is > 0
            } while (K > 0);   // continue only if K > 0

         } // end main()

         static void Print3NSequence(int startingValue) {

            // prints a 3N+1 sequence on the console, using
            // startingValue as the initial value of N

            int N = startingValue;  // N represents a term in the sequence.
            int count = 1;   // count is the number of terms found.
            int onLine = 1;  // onLine counts terms on current output line.

            console.putln("The 3N+1 sequence starting from " + N);
            console.put(N, columnWidth);  // print initial term of sequence

            while (N > 1) {
                N = nextN(N);  // compute next term
                count++;   // count this term
                if (onLine == numberOfColumns) { // if current output line is full
                   console.putln();  // then output a carriage return
                   onLine = 0;   // and note that there are no terms on the new line
                console.put(N, columnWidth);  // print this term
                onLine++;   // add 1 to record of number of terms on this line

            console.putln();  // end current line of output
            console.putln();  // and then add a blank line
            console.putln("There were " + count + " terms in the sequence.");

         }  // end of Print3NSequence()
         static int nextN(int currentN) {
             // computes and returns the next term in a 3N+1 sequence
             if (currentN % 2 == 1)
                return 3 * currentN + 1;
                return currentN / 2;
         }  // end of nextN()
      } // end of class ThreeN

Here is an applet version of this program for you to try:

Sorry, your browser doesn't
support Java.

[ Next Section | Previous Section | Chapter Index | Main Index ]