Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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