PI and a radius variable
r helped, since we don't have to continually write out
the value of pi.
However, we still had to keep writing the formula over and over.
For example, we have to say r * r every time we want to
square the radius, and then we have to remember to multiply by PI.
Let's first address the problem of squaring a number. Instead of
having to write the expression r * r every time, It would
be nice to have a black box, or a procedure, that would take in
a numerical argument and return the square of that argument.

If we had this, we could write
square(837)instead of
837 * 837.
This may not save us much typing
but one can argue that the code is more readable, and certainly if
we were taking cubes or higher powers, it would become ridiculous to
start stringing the numbers all out in a line.
In Java, we can create a procedure called square
as follows:
double square(double x) {
return (x * x);
}
The "double" at the beginning is the type of return value from the
procedure. This is followed by the name of the procedure, and then a
list of formal parameters separated by commas. In this case,
there is only one formal parameter, called x and its type
is double.
When the procedure is invoked, the actual values passed in from the procedure call are bound to the formal parameters. The part in curly braces ({}) is the procedure body. The procedure body contains some number of statements that are executed in order. When one of the formal parameters is used inside the body, it's value is the value that was passed in from the calling procedure. The expression in the return statement is evaluated at the end of the execution of the procedure and the resulting value is returned to the calling procedure as the value of the procedure call.
Now let's invoke the procedure. Suppose we execute the line
double area3 = square(3);The value 3 is called the actual parameter to which the formal parameter x will be bound. Java creates a little binding table
for use inside the
procedure and then evaluates the procedure body using that binding
table. This little binding table is called an environment.
So, the actual parameter 3 is passed into the procedure square
and bound to the variable x. Then the body of the procedure is executed.
The return value 9 is computed, returned as the value of
the expression "square(3)", and subsequently assigned to the
variable area3.
Any expressions can be used in the actual parameter list when making a procedure call, provided that the types matche the types of the corresponding formal parameter list. For example,
double x, y;
double r = 3;
x = square(2+1); // 2 + 1 is evaluated, 3 is passed in
y = square(r); // r is evaluated, 3 is passed in
i = square("3"); // ERROR: type String doesn't match double parameter
Example: areaOfCircle
Having a squre procedure is fine, but what we really
want is a procedure called areaOfCircle that compute the
area of a circle, given the radius. Then we could write statements
like
double area5 = areaOfCircle(5);
So, how do we write the procedure? Assuming that we have already defined the constant PI, we can write:
double areaOfCircle(double radius) {
return (PI * square(radius));
}
Notice that we are using the square procedure to compute the square of the radius.
Let's do some more examples of procedures.
Example: hypotenuse
Suppose we are given a procedure sqrt that takes one
parameter (a double) and returns its square root:
We don't know what sqrt is doing inside, but we can use
it anyway because we understand its specification. This is a nice
advantage of procedural abstraction.
Suppose we want a procedure hyp that finds the length of the hypotenuse of a right triangle, given the lengths of the other two sides.
Recalling that the length of the hypotenuse is the squre root of the sum of the squares of the lengths of the sides, we can write:
double hypotenuse(double sideA, double sideB) {
return sqrt(square(sideA) + square(sideB));
}
And we can call the procedure as follows:
double hyp = hypotenuse(3,4);
Let's think about the evaluation step by step, using the substitution model:
hypotenuse(3,4) sqrt(square(3) + square(4)) sqrt((3 * 3) + (4 * 4)) sqrt(9 + 16) sqrt(25) 5
Math. (A
method is a procedure defined as part of a class.)
We'll say more about classes later, but for now you can think of
the math class as a collection of procedures (methods) and constants,
accessed by Math.name-of-method or
Math.name-of-constant. Examples include:
Math.sqrt(double x) // returns the square root of x Math.pow(x,y) // returns x raised to the power y Math.PI // an approximation of piSee the Math class documentation for a complete list of the available methods and constants.
Another useful class is the Terminal class we have provided as
part of the cs101 package. You will use it to print textual output
from your program to the screen,
as in the following example.
A Complete Program
Let's write a complete program using the procedures we have created.
The program calculates hypotenuses of some right triangles.
public class Triangles {
public static void main(String args[]) {
test(3,4);
test(9,12);
}
public static double square(double x) {
return (x * x);
}
public static double hypotenuse(double sideA, double sideB) {
return Math.sqrt(square(sideA) + square(sideB));
}
public static void test(double a, double b) {
Terminal.print("A right triangle with sides " + a + " and " + b);
Terminal.println(" has hypotenuse " + hypotenuse(a,b));
}
}
Some notes:
main that will be the entry point of the
program.
Terminal.print method prints its argument to
the screen.
The Terminal.println method is the same, except that
it also goes to the next line after printing.
So, the output of the program would be:
A right triangle with sides 3 and 4 has hypotenuse 5. A right triangle with sides 9 and 12 has hypotenuse 15.
Reduction
Now suppose we want to find the length of the diagonal of a square
with side s.
Using the Pythagorean Theorem, the formula to use would be
Thus, the procedure could be written as
double diagonal(double s) {
return Math.sqrt(2*square(s));
}
However, instead we could use what we've already done. We can
reduce the problem of finding the length of the diagonal of a
square to the problem of finding the hypotenuse of a right triangle.
We've transformed one problem to another. This is called a
reduction.
This is useful in many areas of Computer Science.
double diagonal(double s) {
return hypotenuse(s, s);
}
rect_diag
This would be coded as
double rect_diag(double a, double b) {
return hypotenuse(a, b);
}
Math.abs wasn't built in. Thus, we want a black box
like this:

The mathematical definition of this function is

double abs(double x) {
return ???
Wait! How can we do something different depending on the value of x?
So far, all of our computations have been uniform -- they do the
same thing to every input, regardless of its value.What we want is for the execution to be conditional on some test. For the test, we can use any boolean expression (also known as a predicate). But how do we make the execution conditional on whether the test is true or false?
For this purpose, Java provides conditional statements. One possible form is
if condition // NO SEMICOLON!! consequent;Here, the consequent is executed iff (if and only if) the condition is true. The other possible form is
if condition consequent1; else consequent2;Here, if the condition is true, then consequent1 is executed; otherwise, consequent2 is executed.
Using this construct, the abs example could be written as
double abs(double x) {
if (x > 0)
return x;
else if (x == 0)
return 0;
else
return -x;
}
We can shorten this a bit, but it's important to check that all
possible cases are covered!
double abs(double x) {
if (x >= 0)
return x;
else
return -x;
}
Notice that execution continues after the conditional statement,
so we could also have written
double abs(double x) {
if (x >= 0)
return x;
return -x;
}
Note: indentation has no meaning in Java. It is only used for readability.

boolean inside(int x1, int y1, int x2, int y2, int px, int py) {
return ((px >= x1) && (px <= x2) && (py >= y1) && (py <= y2));
}
Now we can use this procedure as a test in a conditional statement.
For example,

if inside(3, 3, 10, 12, 5, 7) // rectangle: 3,3,10,12; point: 5,7
Terminal.println("The point is inside the rectangle.");
else
Terminal.println("The point is outside the rectangle.");
We can also use the results of procedures within boolean
expressions. This is often useful in tests in conditional statements.
if (hypotenuse(3, 4) != 5)
Terminal.println("Error in hypotenuse test.");
if ... {
---;
---;
}
else {
---;
---;
}
or
if ... ---; else ---;
if (y > Math.sqrt(z)) ...;
if !(y < Math.sqrt(z)) ...;
return true and return false
as consequents. For example, instead of
if exp return true; else return false;write
return exp;