This section begins with a discussion of the Number class in java.lang and its subclasses. In particular, this section talks about why you might need these classes, points out the common methods and class variables they have in common, and shows you how to convert instances to strings.
Additionally, this section talks about other classes you might need to work with numbers. For instance, if you need to display a number in a particular format, you can use the NumberFormat and DecimalFormat classes in java.text to format them. Also, the Math class in java.lang contains class methods that perform mathematical functions beyond those provided by the language. This class has methods for the trigonometric functions, exponential functions, and so on.
The Number Classes
Figure 52 shows the class hierarchy for the number classes the Java platform provides.
Figure 52. The class hierarchy of Number.
In addition to the number classes, the Java platform includes the Boolean, [1] Character, [2] and Void [3] classes, which together with the number classes are known as the type-wrapper classes.
[1] http://java.sun.com/j2se/1.3/docs/api/java/lang/Boolean.html
[2] http://java.sun.com/j2se/1.3/docs/api/java/lang/Character.html
[3] http://java.sun.com/j2se/1.3/docs/api/java/lang/Void.html
You might wonder why the type-wrapper classes are necessary, as they seem to duplicate the primitive data types. The type-wrapper classes have several uses.
Furthermore, BigInteger and BigDecimal extend the primitive data types in that they allow for arbitrary-precision numbers (numbers that might not fit into any of the primitive data types). Note that whereas the other classes are in the java.lang package, BigDecimal and BigInteger are in java.math.
Here's an example, called NumberDemo, [1] that creates two Float objects and one Double object and then uses compareTo and equals to compare them:
|
public class NumberDemo { public static void main(String args[]) { Float floatOne = new Float(14.78f - 13.78f); Float oneAgain = new Float(1.0); Double doubleOne = new Double(1.0); int difference = floatOne.compareTo(oneAgain); if (difference == 0) { System.out.println("floatOne is equal to oneAgain."); } else if (difference < 0) { System.out.println("floatOne is less than oneAgain."); } else if (difference > 0) { System.out.println("floatOne is greater than oneAgain."); } System.out.println("floatOne is " + ((floatOne.equals(doubleOne)) ? "equal" : "not equal") + " to doubleOne."); } }
The output from this program might surprise you a little:
floatOne is equal to oneAgain. floatOne is not equal to doubleOne.
Even though the values contained in floatOne and doubleOne are both numerically equal to 1, they are considered unequal because the objects are of different types.
Table 32 lists the instance methods that all the subclasses of the Number class contain, including the compareTo and equals methods used in the preceding example.
Method |
Description |
---|---|
byte byteValue()[a] short shortValue()[b] int intValue() long longValue() float floatValue() double doubleValue() |
Convert the value of this number object to the primitive data types of byte, short, int, long, float, and double. |
int compareTo(Integer)[c] int compareTo(Object)[d] |
Compare this number object to the argument. This method returns a number less than, equal to, or greater than 0, indicating that this number object is, respectively, less than, equal to, or greater than the argument. |
boolean equals(Object) |
Determine whether this number object is equal to the argument. |
[a] Added to the Number class and its subclasses for JDK 1.1.
[b] Added to the Number class and its subclasses for JDK 1.1.
[c] Added to the Number subclasses for Java 2 SDK 1.2.
[d] Added to the Number subclasses for Java 2 SDK 1.2.
As a group, the Number subclasses also contain some useful constants. Recall the MaxVariablesDemo program shown on page 67 in the chapter Language Basics (page 65). That program displays the value of the MAX_VALUE constant for each of the following classes: Byte, Short, Integer, Long, Float, and Double. Each of these classes defines this constant, which contains the largest value that can be held by an instance of that class. Each of these classes also defines a constant named MIN_VALUE, which contains the smallest value that can be held by an instance of that class. To refer to one of these constants, you concatenate the class name, with a dot (.), with the constant name, like this: Integer.MIN_VALUE.
Table 33 lists other useful constants in the Float and Double classes:
Constant |
Description |
---|---|
Float.NaN Double.NaN |
Not a Number. Returned by certain methods in the java.lang.Math class when the result is undefined for the arguments passed to the method. |
Float.NEGATIVE_INFINITY Double.NEGATIVE_INFINITY |
The negative infinity value for a float or a double. |
Float.POSITIVE_INFINITY Double.POSITIVE_INFINITY |
The positive infinity value for a float or a double. |
Converting Strings to Numbers
Sometimes, a program ends up with numeric data in a string objecta value entered by the user, for example. The numeric type-wrapper classes (Byte, Integer, Double, Float, Long, and Short) each provide a class method named valueOf that converts a string to an object of that type. Here's a small example, ValueOfDemo, [1] that gets two strings from the command line, converts them to numbers, and performs arithmetic operations on the values:
|
public class ValueOfDemo { public static void main(String[] args) { //this program requires two arguments on the command line if (args.length == 2) { //convert strings to numbers float a = Float.valueOf(args[0]).floatValue(); float b = Float.valueOf(args[1]).floatValue(); //do some arithmetic System.out.println("a + b = " + (a + b) ); System.out.println("a - b = " + (a - b) ); System.out.println("a * b = " + (a * b) ); System.out.println("a / b = " + (a / b) ); System.out.println("a % b = " + (a % b) ); } else { System.out.println("This program requires two " + "command-line arguments."); } } }
The following is the output from the program when you use 4.5 and 87.2 for the command line arguments:
a + b = 91.7 a - b = -82.7 a * b = 392.4 a / b = 0.0516055 a % b = 4.5
Converting Numbers to Strings
Sometimes, you need to convert a number to a string because you need to operate on the value in its string form. All classes inherit a method called toString from the Object class. The type-wrapper classes override this method to provide a reasonable string representation of the value held by the number object. The following program, ToStringDemo, [1] uses the toString method to convert a number to a string. Next, the program uses some string methods to compute the number of digits before and after the decimal point:
|
public class ToStringDemo { public static void main(String[] args) { String s = Double.toString(858.48); int dot = s.indexOf('.'); System.out.println(s.substring(0, dot).length() + " digits before decimal point."); System.out.println(s.substring(dot+1).length() + " digits after decimal point."); } }
The output from this program is:
3 digits before decimal point. 2 digits after decimal point.
The toString method called by this program is the class method. Each of the number classes has an instance method called toString, which you call on an instance of that type.
You don't have to explicitly call the toString method to display numbers with the System.out.println method or when concatenating numeric values to a string. The Java platform handles the conversion by calling toString implicitly.
Formatting Numbers
The toString method is handy for simple conversions, but you might not like the format of its output. For instance, a floating-point number that represents a monetary value in your program should perhaps be formatted with only two decimal points. To get more control over the format of the output of your program, you can use the NumberFormat [2] class and its subclass, DecimalFormat, [3] to format primitive-type numbers, such as double, and their cor-responding wrapper objects, such as Double. The NumberFormat and DecimalFormat classes are in the java.text package.
[2] http://java.sun.com/j2se/1.3/docs/api/java/text/NumberFormat.html
[3] http://java.sun.com/j2se/1.3/docs/api/java/text/DecimalFormat.html
The following code example formats a Double. The getNumberInstance method is a factory method that returns an instance of NumberFormat. The format method accepts the Double as an argument and returns the formatted number in a string:
Double amount = new Double(345987.246); NumberFormat numberFormatter; String amountOut; numberFormatter = NumberFormat.getNumberInstance(); amountOut = numberFormatter.format(amount); System.out.println(amountOut);
The last line of code prints 345,987.246.
Note
The output you see when you run the previous code snippet might be different from that shown because the NumberFormat and the DecimalFormat classes are locale-sensitivethey tailor their output according to locale. A locale is an object that identifies a specific geographical, political, or cultural region. The locale is not explicitly set in the previous code snippet; thus, the number format object uses the default locale for the current invocation of the Java VM. The output shown here is the output you get when the default locale specifies the United States. You can use the Locale.getDefault method to figure out what the current default locale is, and you can use Locale.setDefault to change it.
An alternative to changing the default locale for the current invocation of the Java VM is to specify the locale when you create a number format object. Instead of using the default locale, the number format object uses the one specified when it was created. Here's how you would create a number format object that tailors its output for France:
NumberFormat numberFormatter = NumberFormat.getNumberInstance(Locale.FRANCE);
This note applies to all the format examples, including those that use the DecimalFormat class, in the rest of this section. For more information, refer to "Internationalization" in The Java Tutorial Continued book, which is also available online and on this book's CD.
Formatting Currencies
If you're writing business applications, you'll probably need to format and to display currencies. You format currencies in the same manner as numbers, except that you call getCurrencyInstance to create a formatter. When you invoke the format method, it returns a string that includes the formatted number and the appropriate currency sign.
This code example shows how to format currency:
Double currency = new Double(9876543.21); NumberFormat currencyFormatter; String currencyOut; currencyFormatter = NumberFormat.getCurrencyInstance(); currencyOut = currencyFormatter.format(currency); System.out.println(currencyOut);
The last line of code prints: $9,876,543.21.
Formatting Percentages
You can also use the methods of the NumberFormat class to format percentages. To get the formatter, invoke the getPercentInstance method. With this formatter, a decimal fraction, such as 0.75, is displayed as 75%.
The following code sample shows how to format a percentage:
Double percent = new Double(0.75); NumberFormat percentFormatter; String percentOut; percentFormatter = NumberFormat.getPercentInstance(); percentOut = percentFormatter.format(percent); System.out.println(percentOut);
The last line of code prints 75%.
Formatting Numbers with Custom Formats
You can use the DecimalFormat class to format decimal numbers into strings. This class allows you to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. If you want to change formatting symbols, such as the decimal separator, you can use the DecimalFormatSymbols [1] class, also in the java.text package, in conjunction with DecimalFormat. These classes offer a great deal of flexibility in the formatting of numbers, but they can make your code more complex.
[1] http://java.sun.com/j2se/1.3/docs/api/java/text/DecimalFormatSymbols.html
The text that follows uses examples that demonstrate the DecimalFormat and the DecimalFormatSymbols classes. The code examples in this material are from a sample program called DecimalFormatDemo. [2]
|
Constructing Patterns
You specify the formatting properties of DecimalFormat with a string pattern. The pattern determines what the formatted number looks like. The example that follows creates a formatter by passing a pattern string to the DecimalFormat constructor. The format method accepts a double value as an argument and returns the formatted number in a string:
DecimalFormat myFormatter = new DecimalFormat(pattern); String output = myFormatter.format(value); System.out.println(value + " " + pattern + " " + output);
The output for the preceding lines of code is described in Table 34. The value is the number, a double, that is to be formatted. The pattern is the String that specifies the formatting properties. The output, which is a string, represents the formatted number.
Value |
Pattern |
Output |
Explanation |
---|---|---|---|
123456.789 |
###,###.### |
123,456.789 |
The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator. |
123456.789 |
###.## |
123456.79 |
The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up. |
123.78 |
000000.000 |
000123.780 |
The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#). |
12345.67 |
$###,###.### |
$12,345.67 |
The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output. |
12345.67 |
u00A5###,###.### |
¥12,345.67 |
The pattern specifies the currency sign for Japanese yen (¥) with the Unicode value 00A5. |
Altering the Formatting Symbols
You can use the DecimalFormatSymbols class to change the symbols that appear in the formatted numbers produced by the format method. These symbols include the decimal separator, the grouping separator, the minus sign, and the percent sign, among others.
The next example demonstrates the DecimalFormatSymbols class by applying a strange format to a number. The unusual format is the result of the calls to the setDecimalSeparator, setGroupingSeparator, and setGroupingSize methods.
DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(currentLocale); unusualSymbols.setDecimalSeparator('|'); unusualSymbols.setGroupingSeparator('^'); String strange = "#,##0.###"; DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols); weirdFormatter.setGroupingSize(4); String bizarre = weirdFormatter.format(12345.678); System.out.println(bizarre);
When run, this example prints the number in a bizarre format:
1^2345|678
Beyond Basic Arithmetic
The Java programming language supports basic arithmetic computation with its arithmetic operators: +, -, *, /, and %. In the java.lang package, the Java platform provides a class called Math [1] that provides methods and variables for doing more advanced mathematical computation, such as computing the sine of an angle, or raising a number to a certain power.
[1] http://java.sun.com/j2se/1.3/docs/api/java/lang/Math.html
The methods in the Math class are class methods, so you call them directly from the class, like this:
Math.round(34.87);
The first set of methods in the Math class that we are going to look at perform various basic mathematical functions, such as computing a number's absolute value and rounding numbers. Table 35 lists and describes these methods.
Method |
Description |
---|---|
double abs(double) float abs(float) int abs(int) long abs(long) |
Returns the absolute value of the argument. |
double ceil(double) |
Returns the smallest double value that is greater than or equal to the argument and is equal to a mathematical integer. |
double floor(double) |
Returns the largest double value that is less than or equal to the argument and is equal to a mathematical integer. |
double rint(double) |
Returns the double value that is closest in value to the argument and is equal to a mathematical integer. |
long round(double) int round(float) |
Returns the closest long or int, as indicated by the method's return value, to the argument. |
The following program, BasicMathDemo, [1] illustrates how to use some of these methods:
|
public class BasicMathDemo { public static void main(String[] args) { double aNumber = -191.635; System.out.println("The absolute value of " + aNumber + " is " + Math.abs(aNumber)); System.out.println("The ceiling of " + aNumber + " is " + Math.ceil(aNumber)); System.out.println("The floor of " + aNumber + " is " + Math.floor(aNumber)); System.out.println("The rint of " + aNumber + " is " + Math.rint(aNumber)); } }
Here's the output from this program:
The absolute value of -191.635 is 191.635 The ceiling of -191.635 is -191 The floor of -191.635 is -192 The rint of -191.635 is -192
Two other basic methods in the Math class are min and max. Table 36 shows the different forms of the min and max methods, which compare two numbers and return the smaller or larger, respectively, of the two.
Method |
Description |
---|---|
double min(double, double) float min(float, float) int min(int, int) long min(long, long) |
Returns the smaller of the two arguments. |
double max(double, double) float max(float, float) int max(int, int) long max(long, long) |
Returns the larger of the two arguments. |
MinDemo, [1] shown following, uses min to figure out the smaller of two values:
|
public class MinDemo { public static void main(String[] args) { double enrollmentPrice = 45.875; double closingPrice = 54.375; System.out.println("Your purchase price is: $" + Math.min(enrollmentPrice, closingPrice)); } }
The program correctly prints the smaller price:
Your purchase price is: $45.875
The next set of methods provided by the Math class are exponential functions. In addition to these functions, you can get the value of e, the base of the natural logarithms, by using Math.E.
Method |
Description |
---|---|
double exp(double) |
Returns the base of the natural logarithms, e, to the power of the argument. |
double log(double) |
Returns the natural logarithm of the argument. |
double pow(double, double) |
Returns of value of the first argument raised to the power of the second argument. |
double sqrt(double) |
Returns the square root of the argument. |
The following program, ExponentialDemo, [1] displays the value of e, then calls each of the methods listed in the previous table on arbitrarily chosen numbers:
|
public class ExponentialDemo { public static void main(String[] args) { double x = 11.635; double y = 2.76; System.out.println("The value of e is " + Math.E); System.out.println("exp(" + x + ") is " + Math.exp(x)); System.out.println("log(" + x + ") is " + Math.log(x)); System.out.println("pow(" + x + ", " + y + ") is " + Math.pow(x, y)); System.out.println("sqrt(" + x + ") is " + Math.sqrt(x)); } }
Here's the output you'll see when you run ExponentialDemo:
The value of e is 2.71828 exp(11.635) is 112984 log(11.635) is 2.45402 pow(11.635, 2.76) is 874.008 sqrt(11.635) is 3.41101
The Math class provides a collection of trigonometric functions, which are summarized in Table 38. The value passed into each of these methods is an angle expressed in radians. You can use the toDegrees and toRadians methods [2] to convert from degrees to radians and back. Also, you can use Math.PI to get the value of p.
[2] The toDegrees and toRadians methods were added to the Math class for Java 2 SDK 1.2.
Method |
Description |
---|---|
double sin(double) |
Returns the sine of the specified double value. |
double cos(double) |
Returns the cosine of the specified double value. |
double tan(double) |
Returns the tangent of the specified double value. |
double asin(double) |
Returns the arc sine of the specified double value. |
double acos(double) |
Returns the arc cosine of the specified double value. |
double atan(double) |
Returns the arc tangent of the specified double value. |
double atan2(double) |
Converts rectangular coordinates (b, a) to polar (r, theta). |
double toDegrees(double) [a] double toRadians(double)[a] |
Converts the argument to degrees or radians as indicated by the method name. |
[a] Added to the Math class for Java 2 SDK 1.2.
Here's a program, TrigonometricDemo, [1] that uses each of these methods to compute various trigonometric values for a 45-degree angle:
|
public class TrigonometricDemo { public static void main(String[] args) { double degrees = 45.0; double radians = Math.toDegrees(degrees); System.out.println("The value of pi is " + Math.PI); System.out.println("The sine of " + degrees + " is " + Math.sin(radians)); System.out.println("The cosine of " + degrees + " is " + Math.cos(radians)); System.out.println("The tangent of " + degrees + " is " + Math.tan(radians)); System.out.println("The arc sine of " + degrees + " is " + Math.asin(radians)); System.out.println("The arc cosine of " + degrees + " is " + Math.acos(radians)); System.out.println("The arc tangent of " + degrees + " is " + Math.atan(radians)); } }
The output of this program is as follows:
The value of pi is 3.141592653589793 The sine of 45.0 is 0.8060754911159176 The cosine of 45.0 is -0.5918127259718502 The tangent of 45.0 is -1.3620448762608377 The arc sine of 45.0 is NaN The arc cosine of 45.0 is NaN The arc tangent of 45.0 is 1.570408475869457
Notice that NaN is displayed when the result is undefined for the argument passed into the method. NaN is the acronym for Not a Number. Various methods in the Math class return this value when the result of a particular function is undefined for the argument passed into the method. Both the Double and Float classes contain constants called NaN. By comparing the return value of a method to one of these constants, your program can determine whether the NaN value is returned from a method. Thus, your program can do something reasonable when the mathematical result of a method call is undefined.
The last Math method that we'll cover is random. The random method returns a pseudorandomly selected number between 0.0 and 1.0. The range includes 0.0 but not 1.0. In other words: 0.0 <= Math.random() < 1.0. To get a number in a different range, you can perform arithmetic on the value returned by the random method. For example, to generate an integer between 1 and 10, you would write:
int number = (int)(Math.random() * 10 + 1);
By multiplying the value by 10, the range of possible values becomes 0.0 <= number < 10.0. By then adding 1, the range of possible values becomes 1.0 <= number < 11.0. Finally, by converting the number to an integer with an explicit cast (int), the value is as desired: an integer value between 1 and 10.
Using Math.random is fine if you need to generate a single number. If you need to generate a series of random numbers, you should create an instance of java.util.Random and call methods on that object to generate numbers. The RandomBag class [1] in the online Bingo example uses this technique to generate a random series of bingo balls. The Math.random method uses an instance of java.util.Random to generate its numbers.
|
Summary of Numbers
You use an instance of one of the Number classesByte, Double, Float, Integer, Long, and Shortto contain a number of primitive type. You can also use BigInteger and BigDecimal for arbitrary-precision numbers.
The Number classes include class methods and constants, which are useful in a variety of ways. The MIN_VALUE and MAX_VALUE constants contain the smallest and largest values that can be contained by an object of that type. The byteValue, shortValue, and similar methods convert one numeric type to another. The valueOf method converts a string to a number, and the toString method converts a number to a string.
To format a number to display to an end user, you use the NumberFormat class in the java.text package. When using NumberFormat, you can get a default format for decimal numbers, percentages, or currency. Or, you can design a custom format using patterns.
The Math class contains a variety of class methods for performing mathematical functions. This class includes the trigonometric functions, such as computing sine, cosine, and so on. Math also includes functions for logarithm calculations, as well as basic arithmetic functions, such as rounding. Finally, Math contains a method, random, for generating random numbers.
Questions and Exercises: Numbers
Questions
1: |
Use the API documentation to find the answers to the following questions:
|
2: |
What is the value of the following expression, and why? new Integer(1).equals(new Long(1)) |
Exercises
1: |
Change MaxVariablesDemo (java/nutsandbolts/variables.html) to show minimum values instead of maximum values. You can delete all code related to the variables aChar and aBoolean. What is the output? |
2: |
Create a program that reads an unspecified number of integer arguments from the command line and adds them together. For example, suppose that you enter the following: java Adder 1 3 2 10 The program should display 16 and then exit. The program should display an error message if the user enters only one argument. You can base your program on ValueOfDemo.java. |
3: |
Create a program that is similar to the previous one but has the following differences:
For example, suppose that you enter the following: java FPAdder 1 1e2 3.0 4.754 The program would display 108.75. Depending on your locale, the decimal point might be a comma (,) instead of a period (.). |
Answers
You can find answers to these Questions and Exercises online:
http://java.sun.com/docs/books/tutorial/java/data/QandE/numbers-answers.html
Getting Started
Object-Oriented Programming Concepts
Language Basics
Object Basics and Simple Data Objects
Classes and Inheritance
Interfaces and Packages
Handling Errors Using Exceptions
Threads: Doing Two or More Tasks at Once
I/O: Reading and Writing
User Interfaces That Swing
Appendix A. Common Problems and Their Solutions
Appendix B. Internet-Ready Applets
Appendix C. Collections
Appendix D. Deprecated Thread Methods
Appendix E. Reference