CHAPTER GOALS
To understand integer and floating-point numbers
To recognize the limitations of the numeric types
To become aware of causes for overflow and roundoff errors
To understand the proper use of constants
To write arithmetic expressions in Java
To use the String
type to manipulate character strings
To learn how to read program input and produce formatted output
This chapter teaches how to manipulate numbers and character strings in Java. The goal of this chapter is to gain a firm understanding of these fundamental data types in Java.
You will learn about the properties and limitations of the number types in Java. You will see how to manipulate numbers and strings in your programs. Finally, we cover the important topic of input and output, which enables you to implement interactive programs.
In Java, every value is either a reference to an object, or it belongs to one of the eight primitive types shown in Table 1.
Six of the primitive types are number types; four of them for integers and two for floating-point numbers.
Java has eight primitive types, including four integer types and two floating-point types.
Each of the integer types has a different range—Special Topic 4.2 on page 130 explains why the range limits are related to powers of two. The largest number that can be represented in an int
is denoted by Integer.MAX_VALUE
. Its value is about 2.14 billion. Similarly, Integer.MIN_VALUE
is the smallest integer, about −2.14 billion.
Generally, you will use the int
type for integer quantities. However, occasionally, calculations involving integers can overflow. This happens if the result of a computation exceeds the range for the number type. For example:
int n = 1000000; System.out.println(n * n); // Prints −727379968, which is clearly wrong
The product n * n
is 1012, which is larger than the largest integer (about 2 · 109). The result is truncated to fit into an int
, yielding a value that is completely wrong. Unfortunately, there is no warning when an integer overflow occurs.
If you run into this problem, the simplest remedy is to use the long
type. Special Topic 4.1 on page 130 shows you how to use the BigInteger
type in the unlikely event that even the long
type overflows.
Overflow is not usually a problem for double-precision floating-point numbers. The double
type has a range of about ±10308 and about 15 significant digits. However, you want to avoid the float
type—it has less than 7 significant digits. (Some programmers use float
to save on memory if they need to store a huge set of numbers that do not require much precision.)
Table 4.1. Primitive Types
Size | ||
---|---|---|
The integer type, with range −2,147,483,648 | 4 bytes | |
| The type describing a single byte, with range −128 . . . 127 1 byte | 1 byte |
The short integer type, with range −32,768 . . . 32,767 | 2 bytes | |
The long integer type, with range −9,223,372,036,854,775,808 . . . 9,223,372,036,854,775,807 | 8 bytes | |
The double-precision floating-point type, with a range of about ±10308 and about 15 significant decimal digits | 8 bytes | |
| The single-precision floating-point type, with a range of about ±1038 and about 7 significant decimal digits | 4 bytes |
| The character type, representing code units in the Unicode encoding scheme (see Special Topic 4.5 on page 153) | 2 bytes |
| The type with the two truth values | 1 bit |
Rounding errors are a more serious issue with floating-point values. Rounding errors can occur when you convert between binary and decimal numbers, or between integers and floating-point numbers. When a value cannot be converted exactly, it is rounded to the nearest match. Consider this example:
double f = 4.35; System.out.println(100 * f); // Prints 434.99999999999994
Rounding errors occur when an exact conversion between numbers is not possible.
This problem is caused because computers represent numbers in the binary number system. In the binary number system, there is no exact representation of the fraction 1/10, just as there is no exact representation of the fraction 1/3 = 0.33333 in the decimal number system. (See Special Topic 4.2 on page 130 for more information.)
For this reason, the double
type is not appropriate for financial calculations. In this book, we will continue to use double
values for bank balances and other financial quantities so that we keep our programs as simple as possible. However, professional programs need to use the BigDecimal
type for this purpose—see Special Topic 4.1 on page 130.
In Java, it is legal to assign an integer value to a floating-point variable:
int dollars = 100; double balance = dollars; // OK
But the opposite assignment is an error: You cannot assign a floating-point expression to an integer variable.
double balance = 13.75; int dollars = balance; // Error
You will see in Section 4.3.5 how to convert a value of type double
into an integer.
2. Suppose you want to write a program that works with population data from various countries. Which Java data type should you use?
3. Which of the following initializations are incorrect, and why?
int dollars = 100.0;
double balance = 100;
In many programs, you need to use numerical constants—values that do not change and that have a special significance for a computation.
A typical example for the use of constants is a computation that involves coin values, such as the following:
payment = dollars + quarters * 0.25 + dimes * 0.1 + nickels * 0.05 + pennies * 0.01;
Most of the code is self-documenting. However, the four numeric quantities, 0.25, 0.1, 0.05, and 0.01 are included in the arithmetic expression without any explanation. Of course, in this case, you know that the value of a nickel is five cents, which explains the 0.05, and so on. However, the next person who needs to maintain this code may live in another country and may not know that a nickel is worth five cents.
Thus, it is a good idea to use symbolic names for all values, even those that appear obvious. Here is a clearer version of the computation of the total:
double quarterValue = 0.25; double dimeValue = 0.1; double nickelValue = 0.05; double pennyValue = 0.01; payment = dollars + quarters * quarterValue + dimes * dimeValue + nickels * nickelValue + pennies * pennyValue;
There is another improvement we can make. There is a difference between the nickels
and nickelValue
variables. The nickels
variable can truly vary over the life of the program, as we calculate different payments. But nickelValue
is always 0.05.
In Java, constants are identified with the reserved word final
. A variable tagged as final
can never change after it has been set. If you try to change the value of a final
variable, the compiler will report an error and your program will not compile.
A final
variable is a constant. Once its value has been set, it cannot be changed.
Many programmers use all-uppercase names for constants (final
variables), such as NICKEL_VALUE
. That way, it is easy to distinguish between variables (with mostly lowercase letters) and constants. We will follow this convention in this book. However, this rule is a matter of good style, not a requirement of the Java language. The compiler will not complain if you give a final
variable a name with lowercase letters.
Here is an improved version of the code that computes the value of a payment.
final double QUARTER_VALUE = 0.25; final double DIME_VALUE = 0.1; final double NICKEL_VALUE = 0.05; final double PENNY_VALUE = 0.01; payment = dollars + quarters * QUARTER_VALUE + dimes * DIME_VALUE + nickels * NICKEL_VALUE + pennies * PENNY_VALUE;
Use named constants to make your programs easier to read and maintain.
Frequently, constant values are needed in several methods. Then you should declare them together with the instance variables of a class and tag them as static
and final
. As before, final
indicates that the value is a constant. The static
reserved word means that the constant belongs to the class—this is explained in greater detail in Chapter 8.)
public class CashRegister { // Constants public static final double QUARTER_VALUE = 0.25; public static final double DIME_VALUE = 0.1; public static final double NICKEL_VALUE = 0.05; public static final double PENNY_VALUE = 0.01; // Instance variables private double purchase; private double payment; // Methods ... }
We declared the constants as public
. There is no danger in doing this because constants cannot be modified. Methods of other classes can access a public constant by first specifying the name of the class in which it is declared, then a period, then the name of the constant, such as CashRegister.NICKEL_VALUE
.
The Math
class from the standard library declares a couple of useful constants:
public class Math { ... public static final double E = 2.7182818284590452354; public static final double PI = 3.14159265358979323846; }
You can refer to these constants as Math.PI
and Math.E
in any of your methods. For example,
double circumference = Math.PI * diameter;
The sample program at the end of this section puts constants to work. The program shows a refinement of the CashRegister
class of How To 3.1. The public interface of that class has been modified in order to solve a common business problem.
Busy cashiers sometimes make mistakes totaling up coin values. Our Cash-Register
class features a method whose inputs are the coin counts. For example, the call
register.enterPayment(1, 2, 1, 1, 4);
enters a payment consisting of one dollar, two quarters, one dime, one nickel, and four pennies. The enterPayment
method figures out the total value of the payment, $1.69. As you can see from the code listing, the method uses named constants for the coin values.
ch04/cashregister/CashRegister.java
1
/**2
A cash register totals up sales and computes change due.3
*/4
public class CashRegister5
{6
public static final double QUARTER_VALUE = 0.25;7
public static final double DIME_VALUE = 0.1;8
public static final double NICKEL_VALUE = 0.05;9
public static final double PENNY_VALUE = 0.01;10
11
private double purchase;12
private double payment;13
14
/**15
Constructs a cash register with no money in it.16
*/17
public CashRegister()18
{19
purchase = 0;20
payment = 0;21
}22
23
/**24
Records the purchase price of an item.25
@param amount the price of the purchased item26
*/27
public void recordPurchase(double amount)28
{29
purchase = purchase + amount;
30
}31
32
/**33
Enters the payment received from the customer.34
@param dollars the number of dollars in the payment35
@param quarters the number of quarters in the payment36
@param dimes the number of dimes in the payment37
@param nickels the number of nickels in the payment38
@param pennies the number of pennies in the payment39
*/40
public void enterPayment(int dollars, int quarters,41
int dimes, int nickels, int pennies)42
{43
payment = dollars + quarters * QUARTER_VALUE + dimes * DIME_VALUE44
+ nickels * NICKEL_VALUE + pennies * PENNY_VALUE;45
}46
47
/**48
Computes the change due and resets the machine for the next customer.49
@return the change due to the customer50
*/51
public double giveChange()52
{53
double change = payment - purchase;54
purchase = 0;55
payment = 0;56
return change;57
}58
}
ch04/cashregister/CashRegisterTester.java
1
/**2
This class tests the CashRegister class.3
*/4
public class CashRegisterTester5
{6
public static void main(String[] args)7
{8
CashRegister register = new CashRegister();9
10
register.recordPurchase(0.75);11
register.recordPurchase(1.50);12
register.enterPayment(2, 0, 5, 0, 0);13
System.out.print("Change: ");14
System.out.println(register.giveChange());15
System.out.println("Expected: 0.25");16
17
register.recordPurchase(2.25);18
register.recordPurchase(19.25);19
register.enterPayment(23, 2, 0, 0, 0);20
System.out.print("Change: ");21
System.out.println(register.giveChange());22
System.out.println("Expected: 2.0");23
}24
}
Program Run
Change: 0.25 Expected: 0.25 Change: 2.0 Expected: 2.0
final double CM_PER_INCH = 2.54; and public static final double CM_PER_INCH = 2.54;
5. What is wrong with the following statement sequence?
double diameter = ...; double circumference = 3.14 * diameter;
In the following sections, you will learn how to carry out arithmetic calculations in Java.
Java supports the same four basic arithmetic operations as a calculator—addition, subtraction, multiplication, and division. As you have already seen, addition and subtraction use the familiar +
and -
operators, and the *
operator denotes multiplication. Division is indicated with a /
, not a fraction bar. For example,
becomes
(a + b) / 2
Parentheses are used just as in algebra: to indicate in which order the subexpressions should be computed. For example, in the expression (a + b) / 2
, the sum a + b
is computed first, and then the sum is divided by 2. In contrast, in the expression
a + b / 2
only b
is divided by 2, and then the sum of a
and b / 2
is formed. Just as in regular algebraic notation, multiplication and division bind more strongly than addition and subtraction. For example, in the expression a + b / 2
, the /
is carried out first, even though the +
operation occurs farther to the left.
Incrementing a value by 1 is so common when writing programs that there is a special shorthand for it, namely
items++;
This statement adds 1 to items
. It is easier to type and read than the equivalent assignment statement
items = items + 1;
As you might have guessed, there is also a decrement operator --
. The statement
items--;
subtracts 1 from items
.
The ++
and --
operators increment and decrement a variable.
Division works as you would expect, as long as at least one of the numbers involved is a floating-point number. That is,
7.0 / 4.0 7 / 4.0 7.0 / 4
all yield 1.75. However, if both numbers are integers, then the result of the division is always an integer, with the remainder discarded. That is,
7 / 4
evaluates to 1, because 7 divided by 4 is 1 with a remainder of 3 (which is discarded). Discarding the remainder is often useful, but it can also be a source of subtle programming errors—see Common Error 4.1 on page 142.
If both arguments of the /
operator are integers, the result is an integer and the remainder is discarded.
If you are interested only in the remainder of an integer division, use the %
operator:
7 % 4
is 3, the remainder of the integer division of 7 by 4. The %
symbol has no analog in algebra. It was chosen because it looks similar to /
, and the remainder operation is related to division.
The %
operator computes the remainder of a division.
Here is a typical use for the integer /
and %
operations. Suppose you want to know how much change a cash register should give, using separate values for dollars and cents. You can compute the value as an integer, denominated in cents, and then compute the whole dollar amount and the remaining change:
final int PENNIES_PER_NICKEL = 5; final int PENNIES_PER_DIME = 10; final int PENNIES_PER_QUARTER = 25; final int PENNIES_PER_DOLLAR = 100; // Compute total value in pennies int total = dollars * PENNIES_PER_DOLLAR + quarters * PENNIES_PER_QUARTER + nickels * PENNIES_PER_NICKEL + dimes * PENNIES_PER_DIME + pennies; // Use integer division to convert to dollars, cents int dollars = total / PENNIES_PER_DOLLAR; int cents = total % PENNIES_PER_DOLLAR;
For example, if total
is 243, then dollars
is set to 2 and cents
to 43.
To compute xn, you write Math.pow(x, n)
. However, to compute x2 it is significantly more efficient simply to compute x * x
.
To take the square root of a number, you use the Math.sqrt
method. For example, √x is written as Math.sqrt(x)
.
In algebra, you use fractions, superscripts for exponents, and radical signs for roots to arrange expressions in a compact two-dimensional form. In Java, you have to write all expressions in a linear arrangement.
For example, the subexpression
of the quadratic formula becomes
(-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a)
Figure 2 shows how to analyze such an expression. With complicated expressions like these, it is not always easy to keep the parentheses ( )
matched—see Common Error 4.2 on page 143.
Table 2 shows additional methods of the Math
class. Inputs and outputs are floating-point numbers.
Occasionally, you have a value of type double
that you need to convert to the type int
. Use the cast operator (int)
for this purpose. You write the cast operator before the expression that you want to convert:
double balance = total + tax; int dollars = (int) balance;
Table 4.2. Mathematical Methods
Returns | |
---|---|
| Square root of x (≥0) |
| xy (x>0, or x = 0 and y>0, or x<0 and y is an integer) |
| Sine of x (x in radians) |
| Cosine of x |
| Tangent of x |
| Arc sine (sin−1x∈[−π/2, π/2], x∈[−1, 1]) |
| Arc cosine (cos−1x∈[0, π], x∈[−1, 1]) |
| |
| Arc tangent (tan−1y∈x∈[−π, π]), x may be 0 |
| |
| |
| ex |
| Natural log (ln(x), x > 0) |
| Decimal log (log10(x), x > 0) |
| Closest integer to x (as a |
| Smallest integer >x (as a |
| Largest integer ≤x (as a |
| Absolute value |x| |
| The larger of x and y |
| The smaller of x and y |
The cast (int)
converts the floating-point value balance
to an integer by discarding the fractional part. For example, if balance
is 13.75, then dollars
is set to 13.
You use a cast (
typeName)
to convert a value to a different type.
The cast tells the compiler that you agree to information loss, in this case, to the loss of the fractional part. You can also cast to other types, such as (float)
or (byte)
.
If you want to round a floating-point number to the nearest whole number, use the Math.round
method. This method returns a long
integer, because large floating-point numbers cannot be stored in an int
.
long rounded = Math.round(balance);
If balance
is 13.75, then rounded
is set to 14.
Use the Math.round
method to round a floating-point number to the nearest integer.
Table 4.3. Arithmetic Expressions
n--; n++; n--;
7. What is the value of 1729 / 100
? Of 1729 % 100
?
8. Why doesn't the following statement compute the average of s1, s2
, and s3
?
double average = s1 + s2 + s3 / 3; // Error
9. What is the value of Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
in mathematical notation?
10. When does the cast (long) x
yield a different result from the call Math.round(x)
?
11. How do you round the double
value x
to the nearest int
value, assuming that you know that it is less than 2 · 109?
In the preceding section, you encountered the Math
class, which contains a collection of helpful methods for carrying out mathematical computations. These methods have a special form: they are static methods that do not operate on an object.
That is, you don't call
double root = 100.sqrt(); // Error
In Java, numbers are not objects, so you can never invoke a method on a number. Instead, you pass a number as an explicit parameter to a method, enclosing the number in parentheses after the method name:
double root = Math.sqrt(100);
This call makes it appear as if the sqrt
method is applied to an object called Math
. However, Math
is a class, not an object. A method such as Math.sqrt
that does not operate on any object is called a static
method. (The term "static" is a historical holdover from the C and C++ programming languages. It has nothing to do with the usual meaning of the word.) In contrast, a method that is invoked on an object is class, is called an instance method:
harrysChecking.deposit(100); // deposit is an instance method
A static method does not operate on an object.
Static methods do not operate on objects, but they are still declared inside classes. When calling the method, you specify the class to which the sqrt
method belongs—hence the call is Math.sqrt(100)
.
How can you tell that Math
is a class and not an object? By convention, class names start with an uppercase letter (such as Math
or BankAccount
). Objects and methods start with a lowercase letter (such as harrysChecking
and println
). Therefore, harrysChecking.deposit(100)
denotes a call of the deposit
method on the harrysChecking
object inside the System
class. On the other hand, Math.sqrt(100)
denotes a call to the sqrt
method inside the Math
class.
This use of upper- and lowercase letters is merely a convention, not a rule of the Java language. It is, however, a convention that the authors of the Java class libraries follow consistently. You should do the same in your programs so that you don't confuse your fellow programmers.
13. Is the call System.out.println(4)
a static method call?
Many programs process text that consists of characters: letters, numbers, punctuation, spaces, and so on. A string is a sequence of characters, such as "Hello, World!"
. In the following sections, you will learn how to work with strings in Java.
In Java, strings are objects that belong to the class String
. (You can tell that String
is a class name because it starts with an uppercase letter. The primitive types int
and double
start with lowercase letters.)
A string is a sequence of characters. Strings are objects of the String
class.
You do not need to call a constructor to create a string object. You can obtain a string literal simply by enclosing a sequence of characters in double quotation marks. For example, the string literal "Harry"
is an object of the String
class.
The number of characters in a string is called the length of the string. As you have seen in Chapter 2, you can use the length
method to obtain the length of a string. For example, "Hello".length()
is 5, and the length of "Hello, World!"
is 13. (The quotation marks are not part of the string and do not contribute to the length, but you must count spaces and punctuation marks.)
A string of length zero, containing no characters, is called the empty string and is written as ""
.
You can use the +
operator to put strings together to form a longer string.
String name = "Dave"; String message = "Hello, " + name;
This process is called concatenation.
The +
operator concatenates two strings, provided one of the expressions, either to the left or the right of a +
operator, is a string. The other one is automatically forced to become a string as well, and both strings are concatenated.
For example, consider this code:
String a = "Agent"; int n = 7; String bond = a + n;
Strings can be concatenated, that is, put end to end to yield a new longer string. String concatenation is denoted by the +
operator.
Because a
is a string, n
is converted from the integer 7 to the string "7"
. Then the two strings "Agent"
and "7"
are concatenated to form the string "Agent7"
.
This concatenation is very useful to reduce the number of System.out.print
instructions. For example, you can combine
System.out.print("The total is "); System.out.println(total);
to the single call
System.out.println("The total is " + total);
The concatenation "The total is " + total
computes a single string that consists of the string "The total is "
, followed by the string equivalent of the number total
.
Whenever one of the arguments of the +
operator is a string, the other argument is converted to a string.
Sometimes you have a string that contains a number, usually from user input. For example, suppose that the string variable input
has the value "19"
. To get the integer value 19
, you use the static parseInt
method of the Integer
class.
int count = Integer.parseInt(input); // count is the integer 19
To convert a string containing floating-point digits to its floating-point value, use the static parseDouble
method of the Double
class. For example, suppose input
is the string "3.95"
.
double price = Double.parseDouble(input); // price is the floating-point number 3.95
However, if the string contains spaces or other characters that cannot occur inside numbers, an error occurs. For now, we will always assume that user input does not contain invalid characters.
If a string contains the digits of a number, you use the Integer.parseInt
or Double.parseDouble
method to obtain the number value.
The substring
method computes substrings of a string. The call
s.substring(start, pastEnd)
returns a string that is made up of the characters in the string s
, starting at position start
, and containing all characters up to, but not including, the position pastEnd
. Here is an example:
String greeting = "Hello, World!"; String sub = greeting.substring(0, 5); // sub is "Hello"
Use the substring
method to extract a part of a string.
The substring
operation makes a string that consists of five characters taken from the string greeting
. A curious aspect of the substring
operation is the numbering of the starting and ending positions. The first string position is labeled 0, the second one 1, and so on. For example, Figure 3 shows the position numbers in the greeting
string.
String positions are counted starting with 0.
The position number of the last character (12 for the string "Hello, World!"
) is always 1 less than the length of the string.
Let us figure out how to extract the substring "World"
. Count characters starting at 0, not 1. You find that W
, the eighth character, has position number 7. The first character that you don't want, !
, is the character at position 12 (see Figure 4).
Therefore, the appropriate substring command is
String sub2 = greeting.substring(7, 12);
It is curious that you must specify the position of the first character that you do want and then the first character that you don't want. There is one advantage to this setup. You can easily compute the length of the substring: It is pastEnd - start
. For example, the string "World"
has length 12 − 7 = 5.
If you omit the second parameter of the substring
method, then all characters from the starting position to the end of the string are copied. For example,
String tail = greeting.substring(7); // Copies all characters from position 7 on sets tail to the string "World!".
If you supply an illegal string position (a negative number, or a value that is larger than the length of the string), then your program terminates with an error message.
In this section, we have made the assumption that each character in a string occupies a single position. Unfortunately, that assumption is not quite correct. If you process strings that contain characters from international alphabets or special symbols, some characters may occupy two positions—see Special Topic 4.5 on page 153.
15. Assuming the String
variable river
holds the value "Mississippi"
, what is the value of river.substring(1, 2)
? Of river.substring(2, river.length() - 3)
?
The Java programs that you have made so far have constructed objects, called methods, printed results, and exited. They were not interactive and took no user input. In this section, you will learn one method for reading user input.
Because output is sent to System.out
, you might think that you use System.in
for input. Unfortunately, it isn't quite that simple. When Java was first designed, not much attention was given to reading keyboard input. It was assumed that all programmers would produce graphical user interfaces with text fields and menus. System.in
was given a minimal set of features—it can only read one byte at a time. Finally, in Java version 5, a Scanner
class was added that lets you read keyboard input in a convenient manner.
To construct a Scanner
object, simply pass the System.in
object to the Scanner
constructor:
Scanner in = new Scanner(System.in);
Use the Scanner
class to read keyboard input in a console window.
You can create a scanner out of any input stream (such as a file), but you will usually want to use a scanner to read keyboard input from System.in
.
Once you have a scanner, you use the nextInt
or nextDouble
methods to read the next integer or floating-point number.
System.out.print("Enter quantity: "); int quantity = in.nextInt(); System.out.print("Enter price: "); double price = in.nextDouble();
When the nextInt
or nextDouble
method is called, the program waits until the user types a number and hits the Enter key. You should always provide instructions for the user (such as "Enter quantity:"
) before calling a Scanner
method. Such an instruction is called a prompt.
If the user supplies an input that is not a number, then a run-time exception occurs. You will see in the next chapter how you can check whether the user supplied a numeric input.
The nextLine
method returns the next line of input (until the user hits the Enter key) as a String
object. The next
method returns the next word, terminated by any white space, that is, a space, the end of a line, or a tab.
System.out.print("Enter city: "); String city = in.nextLine(); System.out.print("Enter state code: "); String state = in.next();
Here, we use the nextLine
method to read a city name that may consist of multiple words, such as San Francisco
. We use the next
method to read the state code (such as CA
), which consists of a single word.
Here is an example of a program that takes user input. This program uses the CashRegister
class and simulates a transaction in which a user purchases an item, pays for it, and receives change.
We call this class CashRegisterSimulator
, not CashRegisterTester
. We reserve the Tester
suffix for classes whose sole purpose is to test other classes.
ch04/cashregister/CashRegisterSimulator.java
1
import java.util.Scanner;2
3
/**4
This program simulates a transaction in which a user pays for an item5
and receives change.6
*/7
public class CashRegisterSimulator8
{
9
public static void main(String[] args)10
{11
Scanner in = new Scanner(System.in);12
13
CashRegister register = new CashRegister();14
15
System.out.print("Enter price: ");16
double price = in.nextDouble();17
register.recordPurchase(price);18
19
System.out.print("Enter dollars: ");20
int dollars = in.nextInt();21
System.out.print("Enter quarters: ");22
int quarters = in.nextInt();23
System.out.print("Enter dimes: ");24
int dimes = in.nextInt();25
System.out.print("Enter nickels: ");26
int nickels = in.nextInt();27
System.out.print("Enter pennies: ");28
int pennies = in.nextInt();29
register.enterPayment(dollars, quarters, dimes, nickels, pennies);30
31
System.out.print("Your change: ");32
System.out.println(register.giveChange());33
}34
}
Enter price: 7.55 Enter dollars: 10 Enter quarters: 2 Enter dimes: 1 Enter nickels: 0 Enter pennies: 0 Your change: 3.05
17. Suppose in
is a Scanner
object that reads from System.in
, and your program calls
String name = in.next();
What is the value of name
if the user enters John Q. Public
?
Choose appropriate types for representing numeric data.
Java has eight primitive types, including four integer types and two floating-point types.
A numeric computation overflows if the result falls outside the range for the number type.
Rounding errors occur when an exact conversion between numbers is not possible.
Write code that uses constants to document the purpose of numeric values.
A final
variable is a constant. Once its value has been set, it cannot be changed.
Use named constants to make your programs easier to read and maintain.
Write arithmetic expressions in Java.
The ++
and --
operators increment and decrement a variable.
If both arguments of the /
operator are integers, the result is an integer and the remainder is discarded.
The %
operator computes the remainder of a division.
The Math
class contains methods sqrt
and pow
to compute square roots and powers.
You use a cast (
typeName)
to convert a value to a different type.
Use the Math.round
method to round a floating-point number to the nearest integer.
Distinguish between static methods and instance methods.
A static method does not operate on an object.
Process strings in Java programs.
A string is a sequence of characters. Strings are objects of the String
class.
Strings can be concatenated, that is, put end to end to yield a new longer string. String concatenation is denoted by the +
operator.
Whenever one of the arguments of the +
operator is a string, the other argument is converted to a string.
If a string contains the digits of a number, you use the Integer.parseInt
or Double.parseDouble
method to obtain the number value.
Use the substring
method to extract a part of a string.
String positions are counted starting with 0.
Write programs that read user input.
Use the Scanner
class to read keyboard input in a console window.
java.io.PrintStream max java.util.Scanner printf min next java.lang.Double pow nextDouble parseDouble round nextInt java.lang.Integer sin nextLine MAX_VALUE sqrt javax.swing.JOptionPane MIN_VALUE tan showInputDialog parseInt toDegrees showMessageDialog toString toRadians java.lang.Math java.lang.String E format PI substring abs java.lang.System acos in asin java.math.BigDecimal atan add atan2 multiply ceil subtract cos java.math.BigInteger exp add floor multiply log subtract log10
• Worked Example Computing the Volume and Surface Area of a Pyramid
• Worked Example Extracting Initials
• Lab Exercises
R4.1 Write the following mathematical expressions in Java.
R4.2 Write the following Java expressions in mathematical notation.
dm = m * (Math.sqrt(1 + v / c) / (Math.sqrt(1 - v / c) - 1));
volume = Math.PI * r * r * h;
volume = 4 * Math.PI * Math.pow(r, 3) / 3;
p = Math.atan2(z, Math.sqrt(x * x + y * y));
R4.3 What is wrong with this version of the quadratic formula?
x1 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 * a; x2 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 * a;
R4.4 Give an example of integer overflow. Would the same example work correctly if you used floating-point?
R4.5 Give an example of a floating-point roundoff error. Would the same example work correctly if you used integers and switched to a sufficiently small unit, such as cents instead of dollars, so that the values don't have a fractional part?
R4.6 Consider the following code:
CashRegister register = new CashRegister(); register.recordPurchase(19.93); register.enterPayment(20, 0, 0, 0, 0); System.out.print("Change: "); System.out.println(register.giveChange());
The code segment prints the total as 0.07000000000000028
. Explain why. Give a recommendation to improve the code so that users will not be confused.
R4.7 Let n
be an integer and x
a floating-point number. Explain the difference between
n = (int) x;
and
n = (int) Math.round(x);
R4.8 Let n
be an integer and x
a floating-point number. Explain the difference between
n = (int) (x + 0.5);
and
n = (int) Math.round(x);
For what values of x
do they give the same result? For what values of x
do they give different results?
R4.9 Consider the vending machine implementation in How To 4.1 on page 146. What happens if the givePennyStamps
method is invoked before the giveFirstClassStamps
method?
R4.10 Explain the differences between 2, 2.0, '2', "2"
, and "2.0"
.
R4.11 Explain what each of the following two program segments computes:
int x = 2; int y = x + x;
and
String s = "2"; String t = s + s;
R4.12 True or false? (x
is an int
and s
is a String
)
Integer.parseInt("" + x)
is the same as x
"" + Integer.parseInt(s)
is the same as s
s.substring(0, s.length())
is the same as s
R4.13 How do you get the first character of a string? The last character? How do you remove the first character? The last character?
R4.14 How do you get the last digit of an integer? The first digit? That is, if n
is 23456
, how do you find out that the first digit is 2
and the last digit is 6
? Do not convert the number to a string. Hint: %, Math.log
.
R4.15 This chapter contains several recommendations regarding variables and constants that make programs easier to read and maintain. Summarize these recommendations.
R4.16 What is a final
variable? Can you declare a final
variable without supplying its value? (Try it out.)
R4.17 What are the values of the following expressions? In each line, assume that
double x = 2.5; double y = −1.5; int m = 18; int n = 4;
x + n * y - (x + n) * y
m / n + m % n
5 * x - n / 5
Math.sqrt(Math.sqrt(n))
(int) Math.round(x)
(int) Math.round(x) + (int) Math.round(y)
1 - (1 - (1 - (1 - (1 - n))))
R4.18 What are the values of the following expressions? In each line, assume that
int n = 4; String s = "Hello"; String t = "World";
s + t
s + n
n + t
s.substring(1, n)
s.length() + t.length()
P4.1 Enhance the CashRegister
class by adding separate methods enterDollars, enterQuarters, enterDimes, enterNickels
, and enterPennies
.
Use this tester class:
public class CashRegisterTester { public static void main (String[] args) { CashRegister register = new CashRegister(); register.recordPurchase(20.37); register.enterDollars(20); register.enterQuarters(2); System.out.println("Change: " + register.giveChange()); System.out.println("Expected: 0.13"); } }
P4.2 Enhance the CashRegister
class so that it keeps track of the total number of items in a sale. Count all recorded purchases and supply a method
int getItemCount()
that returns the number of items of the current purchase. Remember to reset the count at the end of the purchase.
P4.3 Implement a class IceCreamCone
with methods getSurfaceArea()
and getVolume()
. In the constructor, supply the height and radius of the cone. Be careful when looking up the formula for the surface area—you should only include the outside area along the side of the cone since the cone has an opening on the top to hold the ice cream.
P4.4 Write a program that prompts the user for two numbers, then prints
The sum
The difference
The product
The average
The distance (absolute value of the difference)
The maximum (the larger of the two)
The minimum (the smaller of the two)
To do so, implement a class
public class Pair { /** Constructs a pair. @param aFirst the first value of the pair @param aSecond the second value of the pair */ public Pair(double aFirst, double aSecond) { ... } /** Computes the sum of the values of this pair. @return the sum of the first and second values */ public double getSum() { ... } ... }
Then implement a class PairTester
that constructs a Pair
object, invokes its methods, and prints the results.
P4.5 Declare a class DataSet
that computes the sum and average of a sequence of integers. Supply methods
void addValue(int x)
int getSum()
double getAverage()
Hint: Keep track of the sum and the count of the values. Then write a test program DataSetTester
that calls addValue
four times and prints the expected and actual results.
P4.6 Write a class DataSet
that computes the largest and smallest values in a sequence of numbers. Supply methods
void addValue(int x)
int getLargest()
int getSmallest()
Keep track of the smallest and largest values that you've seen so far. Then use the Math.min
and Math.max
methods to update them in the addValue
method. What should you use as initial values? Hint: Integer.MIN_VALUE, Integer.MAX_VALUE
.
Write a test program DataSetTester
that calls addValue
four times and prints the expected and actual results.
P4.7 Write a program that prompts the user for a measurement in meters and then converts it into miles, feet, and inches. Use a class
public class Converter { /**
Constructs a converter that can convert between two units.
@param aConversionFactor
the factor by which to multiply to convert to the target unit
*/ public Converter(double aConversionFactor) { ... }
/**
Converts from a source measurement to a target measurement.
@param fromMeasurement
the measurement
@return
the input value converted to the target unit
*/ public double convertTo(double fromMeasurement) { ... } /**
Converts from a target measurement to a source measurement.
@param toMeasurement
the target measurement
@return
the value whose conversion is the target measurement
*/ public double convertFrom(double toMeasurement) { ... } }
In your ConverterTester
class, construct and test the following Converter
object:
final double MILE_TO_KM = 1.609; Converter milesToMeters = new Converter(1000 * MILE_TO_KM);
P4.8 Write a class Square
whose constructor receives the length of the sides. Then supply methods to compute
The area and perimeter of the square
The length of the diagonal (use the Pythagorean theorem)
P4.9 Implement a class SodaCan
whose constructor receives the height and diameter of the soda can. Supply methods getVolume
and getSurfaceArea
. Supply a SodaCanTester
class that tests your class.
P4.10 Implement a class Balloon
that models a spherical balloon that is being filled with air. The constructor constructs an empty balloon. Supply these methods:
void addAir(double amount)
adds the given amount of air
double getVolume()
gets the current volume
double getSurfaceArea()
gets the current surface area
double getRadius()
gets the current radius
Supply a BalloonTester
class that constructs a balloon, adds 100 cm3 of air, tests the three accessor methods, adds another 100 cm3 of air, and tests the accessor methods again.
P4.11 Giving change. Enhance the CashRegister
class so that it directs a cashier how to give change. The cash register computes the amount to be returned to the customer, in pennies.
Add the following methods to the CashRegister
class:
int giveDollars()
int giveQuarters()
int giveDimes()
int giveNickels()
int givePennies()
Each method computes the number of dollar bills or coins to return to the customer, and reduces the change due by the returned amount. You may assume that the methods are called in this order. Here is a test class:
public class CashRegisterTester { public static void main(String[] args) { CashRegister register = new CashRegister(); register.recordPurchase(8.37); register.enterPayment(10, 0, 0, 0, 0); System.out.println("Dollars: " + register.giveDollars()); System.out.println("Expected: 1"); System.out.println("Quarters: " + register.giveQuarters()); System.out.println("Expected: 2"); System.out.println("Dimes: " + register.giveDimes()); System.out.println("Expected: 1"); System.out.println("Nickels: " + register.giveNickels()); System.out.println("Expected: 0"); System.out.println("Pennies: " + register.givePennies()); System.out.println("Expected: 3"); } }
P4.12 In How To 4.1 on page 146, we represented the state of the vending machine by storing the balance in pennies. This is ingenious, but it is perhaps not the most obvious solution. Another possibility is to store the number of dollars that the customer inserted and the change that remains after giving out the first class stamps. Reimplement the vending machine in this way. Of course, the public interface should remain unchanged.
P4.13 Write a program that reads in an integer and breaks it into a sequence of individual digits in reverse order. For example, the input 16384 is displayed as
4 8 3 6 1
You may assume that the input has no more than five digits and is not negative. Declare a class DigitExtractor
:
Declare a class DigitExtractor: public class DigitExtractor { /** Constructs a digit extractor that gets the digits of an integer in reverse order. @param anInteger the integer to break up into digits */ public DigitExtractor(int anInteger) { ... } /** Returns the next digit to be extracted. @return the next digit */ public int nextDigit() { ... } }
In your main class DigitPrinter
, call System.out.println(myExtractor.nextDigit())
five times.
P4.14 Implement a class QuadraticEquation
whose constructor receives the coefficients a, b, c
of the quadratic equation ax2 + bx + c = 0. Supply methods getSolution1
and getSolution2
that get the solutions, using the quadratic formula. Write a test class QuadraticEquationTester
that constructs a QuadraticEquation
object, and prints the two solutions.
P4.15 Write a program that reads two times in military format (0900, 1730) and prints the number of hours and minutes between the two times. Here is a sample run. User input is in color.
Please enter the first time: 0900 Please enter the second time: 1730 8 hours 30 minutes
Extra credit if you can deal with the case where the first time is later than the second:
Please enter the first time: 1730 Please enter the second time: 0900 15 hours 30 minutes
Implement a class TimeInterval
whose constructor takes two military times. The class should have two methods getHours
and getMinutes
.
P4.16 Writing large letters. A large letter H
can be produced like this:
} }
Declare similar classes for the letters E, L
, and O
. Then write the message
in large letters.
P4.17 Write a class ChristmasTree
whose toString
method yields a string depicting a Christmas tree:
Remember to use escape sequences.
P4.18 Your job is to transform numbers 1, 2, 3, . . ., 12
into the corresponding month names January, February, March, . . ., December
. Implement a class Month
whose constructor parameter is the month number and whose getName
method returns the month name. Hint:Make a very long string "January February March . . . "
, in which you add spaces such that each month name has the same length. Then use substring
to extract the month you want.
P4.19 Write a class to compute the date of Easter Sunday. Easter Sunday is the first Sunday after the first full moon of spring. Use this algorithm, invented by the mathematician Carl Friedrich Gauss in 1800:
Let y
be the year (such as 1800 or 2001).
Divide y
by 19
and call the remainder a
. Ignore the quotient.
Divide y
by 100
to get a quotient b
and a remainder c
.
Divide b
by 4
to get a quotient d
and a remainder e
.
Divide 8 * b + 13
by 25
to get a quotient g
. Ignore the remainder.
Divide 19 * a + b - d - g + 15
by 30
to get a remainder h
. Ignore the quotient.
Divide c
by 4
to get a quotient j
and a remainder k
.
Divide a + 11 * h
by 319
to get a quotient m
. Ignore the remainder.
Divide 2 * e + 2 * j - k - h + m + 32
by 7
to get a remainder r
. Ignore the quotient.
Divide h - m + r + 90
by 25
to get a quotient n
. Ignore the remainder.
Divide h - m + r + n + 19
by 32
to get a remainder p
. Ignore the quotient.
Then Easter falls on day p
of month n
. For example, if y
is 2001
:
a = 6 g = 6 r = 6 b = 20 h = 18 n = 4 c = 1 j = 0, k = 1 p = 15 d = 5, e = 0 m = 0
Therefore, in 2001, Easter Sunday fell on April 15. Write a class Easter
with methods getEasterSundayMonth
and getEasterSundayDay
.
Project 4.1 In this project, you will perform calculations with triangles. A triangle is defined by the x- and y-coordinates of its three corner points.
Your job is to compute the following properties of a given triangle:
the lengths of all sides
the angles at all corners
the perimeter
the area
Of course, you should implement a Triangle
class with appropriate methods. Supply a program that prompts a user for the corner point coordinates and produces a nicely formatted table of the triangle properties.
This is a good team project for two students. Both students should agree on the Triangle
interface. One student implements the Triangle
class, the other simultaneously implements the user interaction and formatting.
Project 4.2 The CashRegister
class has an unfortunate limitation: It is closely tied to the coin system in the United States and Canada. Research the system used in most of Europe. Your goal is to produce a cash register that works with euros and cents. Rather than designing another limited CashRegister
implementation for the European market, you should design a separate Coin
class and a cash register that can work with coins of all types.
int
and double
.
The world's most populous country, China, has about 1.2 x 109 inhabitants. Therefore, individual population counts could be held in an int
. However, the world population is over 6 × 109. If you compute totals or averages of multiple countries, you can exceed the largest int
value. Therefore, double
is a better choice. You could also use long
, but there is no benefit because the exact population of a country is not known at any point in time.
The first initialization is incorrect. The right hand side is a value of type double
, and it is not legal to initialize an int
variable with a double
value. The second initialization is correct—an int
value can always be converted to a double
.
The first declaration is used inside a method, the second inside a class.
(1) You should use a named constant, not the "magic number" 3.14. (2) 3.14 is not an accurate representation of π.
One less than it was before.
17 and 29.
Only s3
is divided by 3. To get the correct result, use parentheses. Moreover, if s1, s2
, and s3
are integers, you must divide by 3.0
to avoid integer division:
(s1 + s2 + s3) / 3.0
When the fractional part of x
is ≥0.5.
By using a cast: (int) Math.round(x)
.
x
is a number, not an object, and you cannot invoke methods on numbers.
No—the println
method is called on the object System.out
.
s
is set to the string "Agent5"
.
The strings "i"
and "ssissi"
.
The class only has a method to read a single byte. It would be very tedious to form characters, strings, and numbers from those bytes.
The value is "John"
. The next
method reads the next word.
3.135.191.86