Download Lab 2 - Christopher Newport University

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
CPSC150L Lab 2
Assignments, Expressions, and Reading User Input
Fall 2016
1
Introduction
In this lab, we will learn how to use variables, assignments, expressions, and the Scanner
class. Since Scanner is provided to us by the Java API, we will also learn how to access and
browse Java’s documentation in order to understand how to use the classes provided by the
Java API.
On Gitlab, clone the repository at https://gitlab.pcs.cnu.edu/cpsc150-students/
cpsc150l-lab02. If you have any problems, see the Git tutorial at http://www.pcs.cnu.
edu/cs150lab/ or ask your instructor. At the end of each section, submit the appropriate
WebCAT assignment for grading.
2
2.1
Exercises
Area of a Circle
We will now write a program that takes a radius as input from the user and outputs the
area of a circle with that radius.
c Christopher Newport University, 2016
1
2.1.1
Area with Integers: Specification
To begin, suppose we have a circle of radius r. Then we know its area is given by the formula
A = πr2
or equivalently
A = π · r · r.
For this section, we will suppose that π = 3.
Create a Java file called Circle.java, and in that file make a class called Circle. In that
class declare the following method.
• public static int area(int r)
This method takes an integer radius and returns the area of a circle with that radius
as an integer.
In this method, declare int pi and int area variables.
Code:
public static int area(int r) {
int pi = 3;
int area = pi*r*r;
return area;
}
2.1.2
Area with Integers: Testing
Test your code by using a Scanner in the main method to take input and pass it to the
method as follows.
2
Code:
public static void main(String[] args) {
int radius;
int a;
Scanner keys = new Scanner(System.in);
System.out.print("Circle’s radius: ");
radius = keys.nextInt();
a = area(radius);
System.out.println("The area is: " + a);
}
Run your program a few times with the following test cases to ensure that it works.
r =2
A = 12
r =7
A = 147
r = 19 A = 1083
2.1.3
Area with Doubles: Specification
So we made a program that calculates area using integers. However, you may have noticed
that we were approximating π with 3. Because of this, our areas are inaccurate! This tells us
that we made the wrong choice when deciding whether to use integers or doubles. Moreover,
our integer implementation only lets us find the area of circles whose radius is an integer
which is rather limiting. To address these limitations, we need to use doubles instead of
integers.
Since we already have the majority of the code written, we just need to edit the code. Our
changes are simple, we just change the return type and types of the r, pi, and area to
double. Moreover, since doubles can handle non-integer values, we will approximate π with
π = 3.14159.
3
2.1.4
Area with Doubles: Testing
Adjust your main so that it uses doubles as opposed to ints. Furthermore, replace your
keys.nextInt() with keys.nextDouble(), this will allow you to read a double from the
keyboard.
Run your program a few times with the following test cases to ensure that it works.
r =2
A = 12.56636
r =7
A = 153.93791
r = 19
A = 1134.11399
r = 15.35 A = 740.229289775
r = 9.362 A = 275.35107695996004
Question 1: Submit Circle.java to WebCAT as Lab 2A.
2.2
Temperature Conversions
In this exercise, we will convert temperatures in Celsius to Fahrenheit and vice versa. The
formulas to do so are
C=
5
(F − 32)
9
F =
9
· C + 32
5
where C is a temperature in Celsius and F is a temperature in Fahrenheit.
To start, make a new Java file called Temperature.java and then make a class named
Temperature. Furthermore, create the following methods.
1. public static double cel2far(double c)
Takes the temperature in Celsius (as a double) as a parameter and returns the temperature in Fahrenheit (as a double).
2. public static double far2cel(double f)
4
Takes the temperature in Fahrenheit (as a double) as a parameter and returns the
temperature in Celsius (as a double).
2.2.1
Testing your Implementation
To test your program, write a main that takes input from the user and passes it to the
methods. Modify the code from Section 2.1.2 to request a double precision temperature
using:
Code:
double temperature = keys.nextDouble();
Use the following test set to test your program.
32◦ F = 0◦ C
107.6◦ F = 42◦ C
14◦ F = −10◦ C
−22◦ F = −30.0◦ C
Do not worry if your output has a trailing .0, that is how Java prints doubles.
If your answers do not match check the following.
1. When multiplying by a fraction, it is generally best to multiply everything by the
numerator and then divide by the denominator.
2. Make sure all of your constants end with a .0. This is because Java treats 9 as an int
and 9.0 as a double. This also affects what the operation returns, for example 9*5
would return an int, but 9.0*5 or 9*5.0 would return a double. The command 9/5
will do integer division and return an integer 1 (that is, Java calculates that 5 goes
into 9 one time with 4 remaining).
Question 2: Submit Temperature.java to WebCAT as Lab2B.
5
2.3
Finding Change
In this exercise, we will take a purchase amount and a payment and determine how many
dollars and coins are needed in order to give proper change. Additionally, we assume that we
have no nickels. For example, suppose a customer pays $35 for a purchase of $32.27. Then
your program should output that we need 2 dollars, 2 quarters, 2 dimes, and 3 pennies.
2.3.1
Specification
Using jEdit, make a new Java file called Money.java. Make a Money class in this file.
Furthermore, declare the following methods.
1. public String change(double paymentDouble, double priceDouble)
Takes a payment amount and a price amount and determines how many dollars, quarters, dimes, and pennies are necessary to give exact change. Assume that paymentDouble
≥ priceDouble. This needs to return a String formatted exactly as follows.
Code:
"$: "+dollars+" Q: "+quarters+" D: "+dimes+" P: "+pennies
Be sure to pay close attention to the format of your output since WebCAT is finicky
and will view your solution as incorrect if your format does not match the expected
format, regardless of your output’s correctness!
Consider the Circle exercise. In Circle.java we initially approximated π by 3, however this
induced a rather large rounding error in our program. We rectified this by approximating π
by 3.14159. However, even with this much better approximation, it is still an approximation.
Therefore, we still induce a rounding error in our program (albeit a much smaller one). In
reality, π has an infinite number of digits in its binary expansion which means that we would
need an infinite amount of memory to even think about storing it exactly (and even then
problems would still exist). The double type usually is a “good enough” approximation to a
real number. When we do arithmetic with doubles, we can potentially introduce more error
with each operation. Thus, when we deal with money we deal with it in cents (an integral
6
value, or an integer) as opposed to dollars (a floating point value, or a number with decimal
places). By doing so, we avoid the inaccuracies that arithmetic using doubles can induce.
After receiving the purchase amount and price, convert the price from dollars to cents and
store it as an integer like so
Code:
int priceInt = 100 * priceDouble;
where priceDouble is the variable you used to get the price amount from the user. Convert
the payment in a similar way. Because of these conversions, you will not lose any information
about the number of cents needed for change. Now how do you calculate the total change
needed (in cents)?
Once you calculate the total change needed (in cents), you can calculate how many dollars,
quarters, dimes, and pennies are needed. Suppose c is the amount of change we need. If we
want to figure out how many dollars are in c, we need to divide c by 100 (the number of
cents per dollar) to get a quotient and remainder. Specifically, we will have
c = 100 · q + r
where q is our quotient (the number of dollars) and r is the remainder (the leftover change).
In Java, when we divide by an integer by an integer, the result is always the quotient. Thus
if change holds the amount of change needed, we use int dollars = change / 100; to
get the number of dollars in it. To get the remainder, we use the modulus operator, %. In
our code we will use change = change % 100; to get the remaining amount of change.
You can now calculate the number of quarters needed, and the remaining change after the
quarters in a similar way, and so on. Once the number of dollars, quarters, dimes, and
pennies has been calculated, return a String that contains all of that information in the
following format.
Code:
"$: "+dollars+" Q: "+quarters+" D: "+dimes+" P: "+pennies
7
2.3.2
Testing
Test your program against the following test cases.
Purchase Payment
$1.01
$10.00
8
3
2
4
$0.48
$1
0
2
0
2
$25.33
$100
74
2
1
7
$10
$10
0
0
0
0
Question 3:
3
Dollars Quarters Dimes Pennies
Submit Money.java to WebCAT under Lab2C for grading.
Common Mistakes
Some solutions to common mistakes in this lab are as follows.
1. Ensure that you use doubles when you need real values and ints when you need
integers.
2. When multiplying by a fraction, multiply by the numerator and then divide by the
denominator. This will lower the amount of information lost when dividing by the
denominator in most cases.
3. If you want a computation to return a double, ensure that the first variable/constant
is a double. This will prevent any loss of information due to truncation. To treat an
integer constant like a double, simply end it with a .0. For example, Java treats 9 as
an int and 9.0 as a double.
4. When dealing with money, always multiply the dollar amount by 100 and then store
it in an int. This will prevent any loss of information due to floating point arithmetic.
5. When doing integer division, a/b yields the quotient and a%b yields the remainder
when a is divided by b.
8
Figure 1: Java Documentation
4
4.1
Tutorial
The Java API
The Java API provides us many classes that we can use in our programs. To get an idea
about how many classes the API gives us, navigate to the following address.
https://docs.oracle.com/javase/8/docs/api/
The webpage shown should look like the one in Figure 1. In the lower left frame, we have
a list of all classes that the API provides. If we click a class in this frame, the right hand
frame will display detailed information about that class. Go ahead and click on the Scanner
class.
9
4.2
The Scanner Class
In the last lab, the programs we created ran without stopping. This worked because all
the data that the program needed was already written in the source code. However, if we
want to run the program with different values, we need to modify the code, recompile, and
finally run the program. This is a rather tedious and cumbersome process that we can avoid
altogether by allowing the user to pass input to the program. To this end, we need to use the
Scanner class which we can use to read input from various sources, including the keyboard.
Consider the following code. The following program will take two numbers from the user
and output their sum, as shown in Figure 2.
Code:
import java.util.Scanner;
public class Sum {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.print("Write the first number: ");
int one = in.nextInt();
System.out.print("Write the second number: ");
int two = in.nextInt();
System.out.println("The sum of " + one + " and " + two +
" is " + (one + two));
}
}
10
Figure 2: Example execution of Sum.java
The above code declares and initializes a new Scanner variable named in that reads from
the keyboard (which Java calls System.in). We then use in to read integers from the user
by invoking Scanner’s nextInt method. When we call the nextInt method, the program
pauses execution until a number is entered and the return key is pressed.
Look at the description of Scanner’s nextInt method in Java’s documentation. While you’re
at it, read the description of Scanner’s nextDouble method. What is the difference between
the values returned by nextInt and nextDouble?
4.3
Program Testing
When learning to program, we must also learn how to thoroughly test our code. In essence,
your programming workflow should look like Figure 3.
When writing a program, we need to ensure that the answers that the program produces are
correct. This is where testing comes into play, but how do we properly test code? The first
method is to try every single input combination possible (called exhaustive testing), however
this is usually too much work. For example, consider Sum.java. In Java, integers can range
11
Code
Start
F inish
Design
T est
Figure 3: Your workflow for lab
from -2147483648 to 2147483647. Thus we have 42949672962 different combinations to test.
If we suppose that each run takes 1 microsecond (10−6 seconds), then the entire test will
take 214 days. This is why we prefer to do a different kind of testing, called boundary value
testing.
Suppose we are writing a program that determines someones pay at the end of each week.
We need to test cases where an employee worked less than 40 hours, exactly 40 hours, and
more than 40 hours. While this form of testing (and most others) are incomplete, they give
us a nice way to determine if a program behaves the way we want it. For this lab, you are
given test sets but in future ones you will need to produce your own.
4.4
Methods and main
In Java, all code runs inside of a method. In the previous lab, you wrote code inside of
something named main. This main is a method. In main, you ran the following line of code.
Code:
System.out.println("Hello World");
In this line you called println, a method of the System.out class, and you passed it the
parameter "Hello World".
While classes are the building blocks of a Java program, methods are the building blocks
of classes. More importantly, methods provide ways to reuse and modularize code within a
class which makes the code
12
1. easier to write,
2. easier to debug,
3. and easier to maintain.
When declaring a method in a class, you need to adhere to the following template.
Code:
public static <returnType> <methodName>(<parameter1,parameter2,...>){
// Code here
}
The public keyword is an access-modifier that specifies what may call the method (in this
case, any class may call the method). The static keyword will be explained in future labs.
The returnType specifies what the method should send back (or return) to the method that
called it. For example, in any main method the return type is void, meaning that main does
not return anything. Whereas, Scanner.nextInt() has a return type of int since it sends
an integer back to the method that called it. When the return type is not void, the method
must end with a return statement. The methodName is, as its name suggests, the name of
the method. This name must start with a letter and can have numbers and underscores in
it. As an aside, the name cannot start with a number and cannot have non alpha-numeric
characters in it. Lastly, after the method name, we have two parentheses inside of which
we place a parameter list. A parameter is a value or object that we pass to the method
we are calling. For example, System.out.println() takes a String parameter and prints
that string to the standard output of your computer. The parameter list can be as long as
you need it to be, and if you do not need any parameters then it can be empty. Here is an
example method declaration.
Code:
public static int sum(int a, int b) {
int vSum;
vSum = a + b;
return vSum;
}
13
The method called sum returns an int and takes two integers as parameters. At the end of
the method, we return the value stored in vSum.
14