Once this form has been customized for your institution, you can use this button to send your lab work. Be sure to read the instructions before starting your work.
To gain experience in
Predictable input will result in predictable output. A function maps element(s) from a problem domain, called parameter(s), into an element from a range of solutions, called the return value.
To treat a function as a "black box", one simply uses it.
For instance, here's a function to compute the volume of a cylinder, say, a beer can, given the height and diameter in millimeters.
/** * computes the volume of a cylinder * @param height the height in millimeters * @param diameter the diameter in millimeters * @return volume - in cubic milliliters */ public static double cylinder_volume(double height, double diameter) { . . . }
To use this function to measure the volume of a can of Blatz Lite, just supply parameters and get its return.
double v = cylinder_volume(2 * can_depth, 1.5 * can_diameter);
Notice that you can use the function without knowing what's inside. Actually, this function is quite simple
public static double cylinder_volume(double height, double diameter) { double volume = Math.PI * diameter * diameter * height / 4; return volume; }
Suppose, instead of milliliters, an answer in fluid ounces is needed, say for a recipe. Use the following functions, together with cylinder_volume to implement a US measurement version public static double cylinder_volume_oz(double height, double diameter) like this:
import ccj.*; public class Cylinder { /** * convert inches to millimeters * Note: 1 inch = 25.4 millimeters * @param inches value in inches to convert to millimeters * @return the converted value */ public static double inch_to_mm(double inches) { return inches * MM_PER_INCH; } /** * convert cubic millimeters to U.S. ounces * Note: 1 fluid U.S. ounce = 29.586 milliliters * @param mm3 - volume in cubic millimeters * @return volume in ounces */ public static double mm_cubed_to_oz(double mm3) { return value_to_convert / MM_CUBED_PER_OZ; } /** * computes the volume of a cylinder * @param height the height in millimeters * @param diameter the diameter in millimeters * @return volume - in cubic milliliters */ public static double cylinder_volume(double height, double diameter) { double volume = Math.PI * diameter * diameter * height / 4; return volume; } /** * computes the volume of a cylinder * @param height the height in inches * @param diameter the diameter in inches * @return volume - in fl. oz. */ public static double cylinder_volume_oz(double height, double diameter) {
} public static void main(String[] args) { System.out.println("Please enter the height (in inches)"); double height = Console.in.readDouble(); System.out.println("Please enter the diameter (in inches)"); double diameter = Console.in.readDouble(); double volume = cylinder_volume_oz(height, diameter); System.out.println("The volume is " + volume + " ounces"); } public static final double MM_PER_INCH = 25.4; public static final double MM_CUBED_PER_OZ = 29.586; }
Productivity Hint 5.1 in the text suggests several enhancements to the future value function. Here is the function from the text.
import ccj.*; public class Futval { /** * computes the value of an investment with compound interest, compounded monthly * @param initial_balance the initial value of the investment * @param p the interest rate as a percent * @param nyear the number of years the investment is held * @return the balance after nyears years */ public static double futureValue(double initial_balance, double p, int nyear) { double b = initial_balance * Math.pow(1 + p / (12 * 100), 12 * nyear); return b; } public static void main(String[] args) { System.out.print("Please enter the initial investment: "); double initial_balance = Console.in.readDouble(); System.out.print("Please enter the interest rate in percent: "; double rate = Console.in.readDouble(); System.out.print("Please enter the number of years: "; double nyears = Console.in.readInt(); double balance = futureValue(initial_balance, rate, nyears); System.out.println("After " + nyears + ", the initial investment of " + initial_balance + " grows to " + balance); } }
Change the futureValue function to compute the value of the investment when there are npayments regular interest payments per year (instead of 12 monthly payments). Supply a main function that calls your changed function.
/* paste program here */
What is the value of a $2000 investment after 6 years at 12 percent if interest is compounded quarterly?
Change the futureValue function to accept holding an investment for a fractional number of years, fyears. Supply a main function that calls your changed function./* paste program here */
What is the value of a $2000 investment after 6.5 years at 12 percent if interest is compounded weekly (52 weeks/year)?
The following code can be used to test a text mode function's interface. It's called a test harness, because any function can be used in it, simply by replacing foo() with the new function call and the desired parameters and returns.
import ccj.*; public class TestHarness { /** * Test harness for calls to console programs * Used to test parameter and return passing. * @param n programmer specified parameter * @return programmer specified return value */ public static double foo(int n) { System.out.println("Got to " + "foo" + " with parameter " + n); return n * 0.1; /* to simulate function activity */ } public static void main() { int give = 3; /* any test value can be entered here */ double get = foo(give); System.out.println("Returned from " + "foo" + " with " + get); } }
Why are the following functions badly named? Try using them in the test harness. What happened? What names would be better?
Sooner or later, you'll encounter cryptically named and uncommented work like the following.
public static bool cn(Employee e1, Employee e2) { return e1.getName() == e2.getName(); } public static bool cs(Employee e1, Employee f) { return e1.getSalary() == f.getSalary(); } public static bool c4dup(Employee joe, Employee mary) { return cn(joe, mary) && cs(joe, mary); } public static void main(String[] args) { Employee john; Employee jane; . . . if(c4dup(john, jane)) System.out.println("Same"); else System.out.println("Different"); }
What do these functions do ?
Rewrite them with comments and more descriptive function and parameter names. Use:
/** * purpose * @param * @return */
In functions with more complicated branching of control, one way to insure a reasonable return value is to gather together all the possibilities and issue only one return statement from the very end of the block statement. Rewrite the pointsOfCompass function as follows:
import ccj.*; public class Compass { /** * Convert a numeric compass position to it's verbal equivalent * @param degrees the compass needle angle in degrees * @return the value as a compass direction ("N", "NE", ...) */ String pointsOfCompass(int degrees) { double octant = (degrees % 360) / 45.0 - 0.5; if (octant >= 7) return "North West"; else if (octant >= 6) return "West"; else if (octant >= 5) return "South West"; else if (octant >= 4) return "South"; else if (octant >= 3) return "South East"; else if (octant >= 2) return "East"; else if (octant >= 1) return "North East"; else if (octant >= 0) return "North"; else return "North West"; } public static void main(String[] args) { System.out.print("Please enter the compass heading (in degrees): "); int degrees = Console.in.readInt(); String direction = pointsOfCompass(degrees); System.out.println("You are heading " + direction); } }
Consider the following functions:
public static String replace(String s, String a, String b) public static double canVolume(double h, double r)
and these variables:
String greeting = Hello!" int a; int b;
What is wrong with each of the following function calls ?
In Java, a function cannot modify contents of any variables that are passed into it. For example, consider this call to the procedure f:
Employee harry = . . .; int n = . . .; . . . f(harry, n)
After the call, harry still refers to the same employee object as before the call, and n still contains the same number as before the call.
The procedure f can modify the state of the employee object, for example, raise it's salary. But it can't replace the object with a different one.
The procedure cannot modify the value of n at all.
int a = 4; int b = 2; increment(a, b); /* now a is 6, b is 2 */
Employee a = new Employee("Aaronsen, Adam", 34000); int b = 1000; increment(a, b); /* now a's salary is 35000, b is 1000 */
Employee a = new Employee("Aaronsen, Adam", 34000); Employee b = new Employee("Birnbaum, Bruce"); swap(a, b); /* now a is Bruce, b is Adam */
Generally, we want to encourage you to define a variable when you first need it, but you have to pay attention to the scope. Find what's wrong with this function's variable scoping, then fix it.
/** * Select the maximum of three integer values * @param i an integer * @param j an integer * @param k an integer */ public static int maximum(int i, int j, int k) { if (i > j) { int a; a = i; } else { a = j; } if (k > a) { return k; } else { return a; } }
Global (or static) variables may "work", but the advantages they offer are outweighed by the confusion they can cause. Since all functions can set a global variable, it is often difficult to find the guilty party if the global variable is set to the wrong value.
import ccj.*; public class Max { /** * Updates maximum if parameter is larger * @param a the value to compare against maximum * @remark Uses static int maximum */ public static void set_max(int a) { if (maximum < a) { maximum = a; } } public static int max3(int i, int j, int k) { maximum = i; set_max(j); set_max(k); return maximum; } public static void main(String[] args) { System.out.print("Please enter the first integer: "); int i = Console.in.readInt(); System.out.print("Please enter the second integer: "); int j = Console.in.readInt(); System.out.print("Please enter the third integer: "); int k = Console.in.readInt(); int maximum = max3(i, j, k); System.out.println("The maximum is " + maximum); } public static int maximum; }
Re-write max3() to avoid the use of global variables, and to preserve the logic of the function.
A call-tree diagram can help organize a large number of related functions. Consider drawing a house like this one using the code library's graphics functions.
It can be done by organizing calls like these:
drawHouse() drawWindow() drawFront() drawRoof() drawDoor()
into a call tree like this
drawHouse | +---------- drawFront | | | +----------- drawWindow (3 times) | | | +----------- drawDoor | +---------- drawRoof
Write a program that implements these functions to draw a house. (Hint: draw_window needs a parameter to specify the location of the window.)
Modify the intName function of the text book to print numbers in German (or, if you prefer, in another language). Here is how German numbers are formed.
The digit names are as follows:
1 eins 2 zwei 3 drei 4 view 5 fuenf 6 sechs 7 sieben 8 acht 9 neun
The tens are named as follows:
10 zehn 20 zwanzig 30 dreissig 40 vierzig 50 fuenfzig 60 sechzig 70 siebzig 80 achtzig 90 neunzig
As in English, the names of the numbers between 11 and 19 are special.
11 elf 12 zwoelf 13 dreizehn
You can obtain 14 ... 19 from 40 ... 90 by replacing "zig" with "zehn".
14 vierzehn 15 fuenfzehn 16 sechzehn 17 siebzehn 18 achtzehn 19 neunzehn
You also need to know
100 hundert 1000 tausend
So far, this is just as in English, just with different names. However, there is one crazy complication. When forming a number between 21 and 99, the ones come before the tens. For example
23 dreiundzwanzig
is "three and twenty". That is, you first convert the ones, then append the word "und", then convert the tens. This being German, you do not add any spaces at all. For example,
23456 dreiundzwanzigtausendvierhundertsechsundfuenfzig
Write the intName function (and the auxiliary functions that it calls) to produce German number names.
Perform a walkthrough of the German intName with n = 416
Consider a function int digits(int) which finds the number of digits needed to represent an integer. For example, digits(125) is 3 because 125 has three digits (1, 2, and 5). The algorithm is defined as:
if n < 10, then digits(n) equals 1. Else, digits(n) equals digits(n / 10) + 1.
(Why? If n is less than 10, one digit is required. Otherwise, n requires one more digit than n/10.)
For example, if called as int num_digits = digits(1457), the following trace results:
digits(1457) = digits(145) + 1 = digits(14) + 1 + 1 = digits(1) + 1 + 1 + 1 = 1 + 1 + 1 + 1
Do a trace of digits(32767)
Write int digits(int n) to be called by the following main():
public static void main(String[] args) { System.out.print("Please enter a number: "); int testValue = Console.in.readInt(); int ndigits = digits(testValue); System.out.println("You need " + ndigits + " digits to represent " + testValue + " in decimal"); }
Don't forget to send your answers when you're finished.