2.6. STATIC METHODS (FUNCTIONS)
This section is under construction.
A static method in Java is like a mathematical function,
such as the sine function.
In mathematics, a function defines a correspondence between each
domain value and some range value. For example, sin(π/6) = 1/2.
In Java, a static method returns a value based on its argument(s).
For example, Math.sin(Math.PI / 6) evaluates to 0.5.
In some situations, we use static methods to implement
mathematical functions, but our normal reason to use static
methods is to separate our programs into smaller pieces so that we
can implement and debug each piece individually.
Mathematical functions. Many familiar mathematical functions (Math.sin, Math.cos, Math.sqrt, Math.max, Math.min, Math.exp, Math.abs) are defined as static methods in Java's Math library. We use them when appropriate, but not every mathematical function that we might want to use is in a library. So, sometimes we must build our own. We build a library MyMath.java that contains a number of useful functions, some of which are already in the Math library, and some of which are not. First, as a warmup, we'll re-implement the absolute value and square root functions. The absolute value function MyMath.abs is straightforward to implement; the function MyMath.sqrt uses Newton's method to compute the square root of a real number, as in Section 2.3.
public static double abs(double x) {
if (x >= 0) return x;
else return -x;
}
public static double sqrt(double c) {
double EPSILON = 1E-15;
double t = c;
while (MyMath.abs(t - c/t) > EPSILON * t)
t = (c/t + t) / 2.0;
return t;
}
|
If you put MyMath.java in your working directory, you can use the function MyMath.abs interchangeably with Math.abs. The function MyMath.sqrt is similar to Math.sqrt, except that Math.sqrt deals with negative inputs is a more refined manner (throws an exception instead of returning a negative number). Its prototype is
public static double sqrt(double c)
This means that you call the function by passing it a value of type double and it returns another value of type double. (Give terminology and draw picture.) We will return to the significance of the keyword static in Section xyz; for now, just remember to use it as you do with main.
Hyperbolic trigonometric functions.
The previous two functions are already implemented in Java's math library so it would be unnecessary for us to duplicate the work. However, Java's math library only contains a fraction of the mathematical functions that we encounter in science and engineering. Java functions provide the flexibility to create our own, as needed. The functions below implement three hyperbolic trigonometric functions (not in Java 1.4, but will be introduced in Java 1.5).The implementations of cosh and sinh are straightforward translations of the corresponding mathematical formulas. The implementation of tanh is simplified by calling our newly written user-defined functions sinh and cosh, and taking their ratio. The order in which include the functions in our .java file is not important; the Java compiler will be able to sort everything out, even if the code for tanh appears before cosh and sinh. Another useful function that is not included in Java's math library is generating a pseudo-random integer in some range. We have repeatedly used the expression (int) (Math.random() * N) to generate a number between 0 and N-1. Instead of having to do this each time, we prefer to package it as a function.
public static double cosh(double x) { return (Math.exp(x) + Math.exp(-x)) / 2.0; } public static double sinh(double x) { return (Math.exp(x) - Math.exp(-x)) / 2.0; } public static double tanh(double x) { return sinh(x) / cosh(x); }
An orthogonal advantage of maintaining random in a function, is that if we want to change its implementation (e.g., to make it more efficient or more accurate and uniform), we only need to change the code in one place. Other programs that rely on MyMath.random will begin using the improved implementation as soon as we compile it.
public static int random(int N) { return (int) (Math.random() * N); }
Primality testing. In Section 2.3, we wrote a program that takes a command line input N and checks whether or not N is prime. We encapsulate this algorithm in the function isPrime. One interesting feature of this function is that the return statement appears inside a loop. As soon as a return statement is encountered, the function stops executing and returns the value.
public static long isPrime(long N) { for (long i = 2; i*i <= n; i++) { if (n % i== 0) return false; } return true; }
Data analysis. The NCAA requires Division I athletes to earn an SAT score of 820 or above to compete in their first year of college athletics. In 2000, over a million high school students took the SAT exam. The average score was 1019 and the standard deviation was 209. Based on this information, we would like to estimate the fraction of SAT test takers that would not meet the NCAA guidelines. Assuming the SAT scores follow a Gaussian distribution, we can compute this quantity using the cumulative normal density function Φ(z, μ, &sigma), where μ is the average SAT score and σ is the standard deviation. Program SAT.java calculates this percentage using MyMath.Phi.
public class SAT {
public static void main(String args[]) {
double mu = 1019;
double sigma = 209;
double z = 820;
System.out.println(MyMath.Phi(z, mu, sigma));
}
}
|
Gaussian distribution.
We will describe how to implement MyMath.Phi. The Gaussian distribution (a.k.a., the normal distribution) plays a central role in statistics and forms the basis of most data analysis in the physical and social sciences. The probability that a Gaussian random variable with mean 0 and standard deviation 1 is less than z is
where erf(z) known as the error function, and is defined as
For example, Φ(1.96) = 0.975. This means that 97.5% of the area under the standard Gaussian curve is to the left of z = 1.96. Since the normal distribution is symmetric, this means that 95% of the area is between -1.96 and 1.96. Useful number in statistics. The probability that a normal random variable with mean μ and standard deviation σ is less than z is Φ((z - μ) / σ). We implement these functions as follows in MyMath.java.
public static double Phi(double z) {
return 0.5 * (1.0 + erf(z / (Math.sqrt(2.0))));
}
public static double Phi(double z, double mu, double sigma) {
return Phi((z - mu) / sigma);
}
|
This illustrate two important techniques. First, the function Phi calls another function. Second, the function Phi is overloaded: there are two different functions with the same name. The compiler can automatically distinguishes between them according to context since. For example when the second function Phi calls Phi, the compiler knows to use the first one since it expects only a single argument, whereas the second function Phi expects three arguments. In general, you can overload a function as many times as you like, so long as each one has a different prototype (not counting its return type).
Finally, we describe how to compute the error function erf(z). The function MyMath.erf takes one input z and computes the error function of z to 7 significant digits using a Chebyshev fitting estimate. When z is nonnegative, the formula is
erf(z) ~= 1 - t * exp( -z*z - 1.26551223 + 1.00002368 t
+ 0.37409196 t^2 + 0.09678418 t^3
- 0.18628806 t^4 + 0.27886807 t^5
- 1.13520398 t^6 + 1.48851587 t^7
- 0.82215223 t^8 + 0.17087277 t^9
)
where t = 1.0 / (1.0 + 0.5 * z)
|
If z is negative, then use the identity erf(z) = -erf(-z). The formula is quite complicated, and it is not our goal to derive or justify it. Instead, as a Java programmer, we will focus on transcribing it from mathematical notation into Java. This is not difficult. By encapsulating it in a function, we shield the user from the details, and we are free to change the way we implement the function if we discover a more accurate or more efficient formula. We add the function to MyMath.java. We can add similar functions to our library by looking up the appropriate formulas. Our programs can now directly access some of the vast knowledge that has been built up by mathematicians over the past 1,000 years.
Black Scholes option pricing. Now, we'll implement a client program that uses the MyMath library. In 1973, Fisher Black and Myron Scholes published a mathematical model for calculating the value of a European call option. Myron Scholes would later win the 1997 Nobel Prize in Economics for their paper. Their model computes the price of an option based as a function of five variables: the stock price, the strike price, the expiration date, the risk-free return, and the standard deviation (volatility) of the stock's return. A stock option is a contract between two parties that grants the option holder the right to buy a stock at some future date for a fixed price. Since the option holder has a right to buy the stock, but not an obligation, the option have financial value and are sold for a up-front fee called the premium. How much should you be willing to pay for a given stock option?
The Black Scholes formula supplies the theoretical price of a European call option on a stock that does not make dividends, given the current stock price S, the exercise price X, the continuously compounded risk free interest rate r, the standard deviation of the stock's return (volatility) σ, and the time to maturity T. The price is
where
and Φ(z) is the standard normal cdf as in Exercises xyz. Program BlackScholes.java reads in 5 command line parameters S, X, r, σ and T, and prints the theoretical option price according to the Black Scholes model.
Craps. Functions are also useful to break up a large program into smaller, more manageable pieces. Analog: when writing we break up an essay into paragraphs, where each paragraph expresses one coherent idea. Our next example will illustrate this technique to estimate the probability of winning a pass bet in craps. Here are the rule for a pass bet. Roll two 6-sided dice, and let x be their sum.
- if x is 7 or 11, you win instantly
- if x is 2, 3, or 12, you lose instantly
- otherwise, repeatedly roll two dice until their sum is either x or 7
- if their sum is x, you win
- if their sum is 7, you lose
Program Craps.java takes a command line parameter N and simulates N pass bets. The program's organization benefits from two helper functions: sumOfTwoDice and winsPassBet. Both functions have one interesting feature - they do not take any input arguments. The first function simulate the throw of two dice. This returns an integer between 2 and 12, but not all values are equally likely. To simulate the probabilities correctly, we call MyMath.random(6) twice and one to generate a number between 1 and 6. Then, we add the two values. The second function returns a boolean value: true if we win the pass bet and false otherwise. This function has several return statements. As soon as the first one is executed, the function terminates with the given return value.
Passing non primitive types to functions. You can pass values of any type to a function, including strings and arrays. The function duplicate takes a string as input and returns a string which contains two copies of the original string, concatenated together.
The following two statements leaves the string "HelloHello" in the variable s.
public static String duplicate(String s) { String t = s + s; return t; }
The following two statements leaves the string "ByeByeByeByeByeByeByeBye" in the variable s.
String s = "Hello"; s = duplicate(s);
String s = "Bye"; s = duplicate(duplicate(duplicate(s)));
Functions on arrays.
We can write functions whose inputs are arrays.-
The function average takes a double array as input
and returns the average value.
public static average(double[] a) { double sum = 0.0; for (int i = 0; i -
The function shuffle below takes an array of strings
as an argument, and shuffles them in random order as in Section 2.5.
Program Shuffle.java reads
in a sequence of strings from standard input, calls the function
to shuffle them, and then prints them out.
Note that the function changes the values of the individual
array elements.
This is in stark contrast to what happens when
primitive types are passed to functions. We will revisit this
distinction in Section XYZ when we discuss how reference types
(which includes strings and arrays) work in Java.
We refer to a change made by a function to its inputs as
"side effect."
public static void shuffle(String[] a) { for (int i = 0; i
Command line parameters. We have used one static method extensively in every program since Hello, World: main.
public static void main(String[] args) |
The parameter to main is an array of strings. The values passed are strings (delimited by blanks) typed after the program name in the java command. Since main does not return a value back to the operating system, we use the special return type void. The program ParameterDemo.java illustrates this by printing out all of the command line parameters, one per line.
Abstraction.
One important feature of a function is that it hides the implementation details from the user. As long as the function sqrt returns the square root of the input parameter, the user does not know or care whether the function uses Newton's method or some other technique. This principle requires that the function's formal parameters and variables be local to the function. This approach enables us to substitute the function with a different function that has the same behavior. The rest of our program would work exactly as before, without requiring any additional changes.Scope.
Good place to talk about scope within functions and within blocks. Guiding principle: variable should be defined so that its scope is as small as possible.
Lessons
- Use functions to calculate mathematical formulas.
- Use functions to break up a program into smaller, more manageable pieces that can be individually tested and debugged.
- Use the keyword void to designate the return type of a method that doesn't return anything.
- main is a static method just like any other static method. It takes an array of strings as input and returns nothing.
- When you pass a primitive type (int, double, boolean) to a function, you are passing a copy of that value, not the variable itself.
- When you pass an array to a function, you are passing a copy of a reference to that array. The function can change the individual array elements, but it cannot change the array itself (e.g., to resize it).
- Static methods can take multiple parameters, but can return only one value. The parameters and return value can be of any type.
Q + A
Q. Can I return from a void function by using return. If so, what value should it return?
A. Yes. use the statement return; with no return value.
Q. Do I need the keyword static?
A. Yes. In Section XYZ, we'll learn about objects and non-static methods.
Q. Can I return more than one value from a function?
A. No. Sometimes it is convenient to return an array if you need to return several values of the same type. In Chapter 3, we'll learn about a more powerful method for returning groups of related data.
Q. Why can't a function (method) return more than one value?
A. It's partly out of historical precedent and also the common association of mathematical functions with programming functions. It may also have been influenced by the 0-1-infinity principle which says that any feature in a program should be allowed to occur exactly zero times, exactly one time, or infinitely many times. There could be significant overhead in allowing functions to return an arbitrary number of values. Thus, allowing 0 or 1 is a decent tradeoff.
Q. What happens if I write code after a return statement?
A. One a return statement is reached, the function immediately stops executing, so any code after a return statement is useless. The Java compiler flags this as an error, reporting "unreachable code."
Exercises
- Add a static method max2 to MyMath that takes two integers as parameters and returns the value of the larger one.
- Add an overloaded static method max2 to MyMath that takes two real values as parameters and returns the value of the larger one.
- Add a static method max3 to MyMath that takes three integers as parameters and returns the value of the largest one.
- Add a static method nint to MyMath that takes a real number as a parameter and returns the nearest integer. Do not use any Math library function, instead use casting.
- Add a static method random to MyMath that takes an integer n and returns a pseudo-random integer between 0 and n-1. Call the function Math.random which takes a double as input and returns a pseudo-random integer between 0.0 and 1.0.
- Add an overloaded static method random to MyMath that takes two integers a and b, and returns a pseudo-random integer between a and b (inclusive).
- The ACT is another standardized test. Assume that test scores follow a Gaussian distribution with mean 18 and standard deviation 6. Also assume that the test takers for SAT and ACT are indistinguishable. Which is better, an SAT score of 620 or ACT of 26?
- Add a static method gaussian to MyMath that returns a pseudo-random Gaussian with mean 0 and standard deviation 1. Hint: see the corresponding exercise in Section 2.2.
- Add an overloaded static method gaussian to MyMath that takes two real inputs, μ and σ, and returns a pseudo-random Gaussian with mean μ and standard deviation σ. Hint: call the no-argument version of MyMath.gaussian, multiply it by σ and then add μ.
- Add a static method gaussian to MyMath that returns a pseudo-random value from a Maxwell-Boltzmann distribution with parameter σ. To produce such a value, take the sum of the squares of three Gaussian random variables with mean 0 and standard deviation σ, and return the square root. The speeds of molecules in an ideal gas have a Maxwell-Boltzmann distribution, where the parameter σ is related to XYZ.
- Add overloaded static methods lg(int) and lg(long) to MyMath that take an integer or long as input and return the number of bits in the binary representation of its parameter.
-
Write a program Factorial.java
that takes one integer command line input n and prints out
n! = 1 * 2 * ... * n.
Write a function that has the following prototype:
static long factorial(int n)
What is the largest value of n that your function can handle without overflow?
-
What is wrong with the following function?
static int sum(int n) { if (n <0) return; double sum=0.0; for (int i=0; i < n; i++) sum=sum + i; return sum; }Answer: The function is declared to return a value of type int. The first return statement is wrong since it returns nothing. The second return statement is wrong since it returns a value of type double.
- Write a function that takes three real arguments, x, y, and s, and plots an equilateral triangle centered on (x, y) with side length s. Call the function a number of times in main to produce an entertaining pattern. Hint: use StdDraw.rotate and StdDraw.goForward.
- Modify the function above so that it takes a fourth parameter n and plots a regular n-gon centered on (x, y) with side length s.
- Write a function that takes four parameters x, y, and s, and draws a filled square with lower left endpoint (x, y) and side length s. Recall that StdDraw.spot(s, s) draws a filled square of side length s, centered on the turtle's current position.
-
Which of the following functions returns the minimum of its
four inputs? Which is easiest to understand and verify that
it is correct?
public static int min(int a, int b, int c, int d) { // if a is the smallest return it if (a <= b && a <=c && a <=d) return a; // otherwise, if b is the smallest of b, c, and d, return it if (b <=c && b <=d) return b; // otherwise, return the smaller of c and d if (c <=d) return c; return d; } public static int min(int a, int b, int c, int d) { int min=a; if (b < min) min=b; if (c < min) min=c; if (d < min) min=d; return min; } public static int min(int a, int b, int c, int d) { if (a < b && a < c && a < d) return a; if (b < c && b < d) return b; if (c < d) return c; return d; } public static int min(int a, int b, int c, int d) { if (a <=b) { if (a <=c) { if (a <=d) return a; else return d; } if (c <=d) return c; else return d; } if (b <=c) { if (b <=d) return b; else return d; } else if (c <=d) return c; return d; } public static int min(int a, int b) { if (a <=b) return a; else return b; } public static int min(int a, int b, int c, int d) { return min(min2(a, b), min2(c, d)); } -
How would you go about testing whether one of the functions in
the previous exercise does what it claims to do?
Answer: you can't hope to test it on every conceivable input since there are 2128 different possible inputs. Instead, test it on all 4! = 24 cases depending on whether a Write a program that takes a command line input N and prints N random phone numbers of the form (xxx) xxx-xxxx. Use the function MyMath.random. Don't worry about printing the same number twice.
- Write a program to print the lyrics to Old McDonald.
public static String sing(String animals, String sound) { String s = ""; s += "Old MacDonald had a farm\n"; s += "E-I-E-I-O\n"; s += "And on his farm he had some " + animals + "\n"; s += "With a " + sound + "-" + sound + " here\n"; s += "And a " + sound + "-" + sound + " there\n"; s += "Here a " + sound + ", there a " + sound + "\n"; s += "Everywhere a + sound + "-" + sound + "\n"; s += "Old MacDonald had a farm\n"; s += "E-I-E-I-O\n"; return s; } ... System.out.println(sing("chicks", "cluck")); System.out.println(sing("cows", "moo")); System.out.println(sing("pigs", "oink")); System.out.println(sing("cats", "meow")); System.out.println(sing("sheep", "baa")); System.out.println(sing("ducks", "quack")); System.out.println(sing("horses", "neigh"));- Write a function majority that takes three boolean inputs and returns true if at least two are true, and false otherwise. Do not use an if statement. Solution: here are two solutions: the first is concise; the second adheres to the rules, but is rather obfuscated.
public static boolean majority(boolean a, boolean b, boolean c) { return (a && b) || (a && c) || (b && c); } public static boolean majority(boolean a, boolean b, boolean c) { while (a && b) return true; while (a && c) return true; while (b && c) return true; return false; }- Write a function odd that takes three boolean inputs and returns true if an odd number of inputs are true, and false otherwise.
- Write a program to print the lyrics to Old McDonald.
Creative Exercises
- Day of the month. Write a function that takes a month, date, and year and returns which day of the week that date falls on. Hint: see Day.java for the algorithm.
- Day of the month. Write a function that takes an integer and returns true if that integer is a leap year, Hint: see program LeapYear.java for the algorithm.
-
Calendar.
Write a program Calendar that takes two command
line arguments m and y and prints out the monthly
calendar for the mth month of year y. For example,
your output for Calendar 2 2009 should be
February 2009 S M Tu W Th F S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Hint: use the functions from the previous two exercises and use arrays to store the names of the months and the number of days in each month.
-
IBM check.
Mastercard uses the following check
2f(d1) + d2 + 2f(d3) + d4 + 2f(d5) + d6 + ... = 0 (mod 10)
to validate legal account numbers, where d_i are the decimal digits of the account number and f(d) is the sum of the decimal digits of d. Implement the function f() and write a program to read in a XXX digit integer as a command line parameter and output true or false depending on whether it passes the test.
- Euler's totient function. Euler's totient function is an important function in number theory: φ(n) is defined as the number of positive integers less than or equal to n that are relatively prime with n (no factors in common with n other than 1). Write a function that takes an integer input n and φ(n).
- Angle subtended by two stars. Given two stars with angles of declination and right ascension (D1, A1) and (D2, A2), write a function to determine the angle they subtend. Assume A1 and A2 are angles between -180 and 180 degrees and D1 and D2 are angles between -90 and 90 degrees. When V is a small angle, the formula is 2 arcsin * sqrt(sin^2(d/2) + cos (D2)cos(D)sin^2(a/2)), where a = A2 - A1 and d = D2 - D1. Hint: be careful about converting to radians and back.
- Scrambled text.
Cognitive psychologists believe that people recognize words based on their shape.
to a rscheearch at an Elingsh uinervtisy, it deosn't mttaer in waht oredr the ltteers in a wrod are, the olny iprmoetnt tihng is taht frist and lsat ltteer is at the rghit pclae. The rset can be a toatl mses and you can sitll raed it wouthit porbelm. Tihs is bcuseae we do not raed ervey lteter by itslef but the wrod as a wlohe.
Write a program that reads in text from standard input and prints the text back out, but shuffles the internal letters in each word. Write and use a function scramble that takes as input a string and returns another string with the internal letters in random order. Use the shuffling algorithm in Shuffle.java for the shuffling part. - The diameter of pistons manufactured can be modeled by a normal distribution with mean diameter 5 cm and standard deviation 0.001 cm. To meet specifications, the diameter must be between 4.998 and 5.002 cm. What percentage of pistons will meet spec?
- Inverse Gaussian cumulative distribution. Suppose SAT math scores are normally distributed with mean 500 and standard deviation. Estimate how high student must score in order to be among the top 10%. To do this you need to find the value z for which Φ(z, 500, 100) = 0.9. Hint: use binary search.
- SAT scores. A prominent northeastern university receives 20,000 student applications. Assume that the SAT scores of these individuals is normally distributed with mean 1200 and standard deviation 100. Suppose the university decides to admit the 5,000 students with the best SAT scores. Estimate the lowest score that will still be admitted.
- Voting machines. Suppose that in a population of 100 million voters, 51% vote for candidate A and 49% vote for candidate B. However, the voting machines are prone to make mistakes, and 5% of the time they produce the wrong answer. Assuming the errors are made independently and at random, is a 5% error rate enough to invalidate the results of a close election? What error rate can be tolerated?
- Gambler's histogram.
Write a program RandomWalk.
that takes one command line parameter M and simulates a gambler starting
with M who places exactly M one dollar bets.
- Produce a histogram of the amount of money the gambler ends up with by running this experiment N times.
- The amount of money the gambler ends up with follows a binomial distribution with mean M and variance N/4. The distribution can be approximated by a normal distribution with the same mean and variance. Produce a histogram for the fraction of time you'd expect the gambler to end up with the amount in each histogram bin.
- Statistical sampling. Write a program Sampling.java takes a random sample of N people and asks them a yes/no question. Compute a 95% confidence interval.
- Blackjack. Write a program Blackjack.java that plays the basic strategy or write a program BlackjackCounter.java that implements the high-low card counting system.
- Wavelets. Applications to computer vision, human vision, speech processing, compressing the FBI fingerprint database, filtering noisy data, detecting self-similarity in time series, sound synthesis, computer graphics, medical imaging, analyzing the clumping of galaxies, and analyzing turbulence. The Haar function is definite by Φ(x) = 1 if 0 ≤ x <1/2, φ(x)=-1 if 1/2 ≤ x < 1, and φ(x)=0 otherwise. for integer m and n, the Haar basis function Φm,n(x) = 2-m/2 Φ(2-mx - n). Write a program Haar.java that takes two integer input M and N, and one real input x and prints Φm,n(x). Or maybe plot it?
- Baccarat. Baccarat is a simple card game which has been romanticized in James Bond movies. When the player is dealt nine, the croupier proclaims "neuf a la banque". Write a program that determines your chance of winning....
- Collinear points.
Write a function
public boolean areCollinear(int x1, int y1, int x2, int y2, int x3, int y3)that returns true if the three points (x1, y1), (x2, y2), and (x3, y3) lie on the same line, and false otherwise.
