Number formats also handle
input. When
used for input, a number format converts a string in the appropriate
format to a binary number, achieving more flexible conversions than
you can get with the methods in the type wrapper classes (like
Integer.parseInt()
). For instance, a percent
format parse()
method can interpret 57% as 0.57
instead of 57. A currency format can read (12.45) as -12.45.
There are three parse()
methods in the
NumberFormat
class. All do roughly the same thing:
public Number parse(String text) throws ParseException public abstract Number parse(String text, ParsePosition parsePosition) public final Object parseObject(String source, ParsePosition parsePosition)
The first parse()
method attempts to parse a
number from the given text. If the text represents an integer,
it’s returned as an instance of
java.lang.Long
. Otherwise, it’s returned as
an instance of java.lang.Double
. If a string
contains multiple numbers, only the first one is returned. For
instance, if you parse “32 meters” you’ll get the
number 32 back. Java throws away everything after the number
finishes. If the text cannot be interpreted as a number in the given
format, a ParseException
is thrown. The second
parse()
method specifies where in the text parsing
starts. The position is given by a ParsePosition
object. This is a little more complicated than using a simple
int
but does have the advantage of allowing one to
read successive numbers from the same string. The third
parse()
method merely invokes the second.
It’s declared to return Object
rather than
Number
so that it can override the method of the
same signature in java.text.Format
. If you know
you’re working with a NumberFormat
rather
than a DateFormat
or some other nonnumeric format,
there’s no reason to use it.
The java.text.ParsePosition
class has one
constructor and two public methods:
public ParsePosition(int index) public int getIndex() public void setIndex(int index)
This whole class is just a wrapper around an int
position, which is set by the constructor and the
setIndex()
mutator method. It’s returned by
the getIndex()
method. As a
NumberFormat
parses a string, it updates the
associated ParsePosition
’s index. Thus, when
passed into a parse()
method, the
ParsePosition
contains the index where parsing
will begin. When the parse()
method returns, the
ParsePosition
contains the index immediately after
the last character parsed. If parsing fails, the parse position is
unchanged.
Some number formats can only read integers, not floating point
numbers. The isParseIntegerOnly()
method returns
true
if this is the case, false
otherwise.
public boolean isParseIntegerOnly() public void setParseIntegerOnly(boolean value)
The setParseInteger()
method lets you specify that
the format should only parse integers. If a decimal point is
encountered, then parsing should stop.
Example 16.8 is a simple program of the sort that’s common in CS 101 courses. The assignment is to write a program that reads a number entered from the command line and prints its square root. Successive numbers are read until a negative number is entered, at which point the program halts. Although this is a very basic exercise, it’s relatively complex in Java, because Java separates string parsing from basic I/O. Nonetheless, while it may not be suitable for the first week’s homework, students should be able to handle it by the end of the semester.
Example 16-8. RootFinder
import java.text.*; import java.io.*; public class RootFinder { public static void main(String[] args) { Number input = null; try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); NumberFormat nf = NumberFormat.getInstance(); while (true) { System.out.println("Enter a number (-1 to quit): "); String s = br.readLine(); try { input = nf.parse(s); } catch (ParseException e) { System.out.println(s + " is not a number I understand."); continue; } double d = input.doubleValue(); if (d < 0) break; double root = Math.sqrt(d); System.out.println("The square root of " + s + " is " + root); } } catch (IOException e) {System.err.println(e);} } }
Here’s a sample run:
%java RootFinder
Enter a number (-1 to quit):87
The square root of 87 is 9.327379053088816 Enter a number (-1 to quit):3.151592
The square root of 3.151592 is 1.7752723734683644 Enter a number (-1 to quit):2,345,678
The square root of 2,345,678 is 1531.5606419596973 Enter a number (-1 to quit):2.998E+8
The square root of 2.998E+8 is 1.7314733610425546 Enter a number (-1 to quit):299800000
The square root of 299800000 is 17314.733610425545 Enter a number (-1 to quit):0.0
The square root of 0.0 is 0.0 Enter a number (-1 to quit):four
four is not a number I understand. Enter a number (-1 to quit):4
The square root of 4 is 2.0 Enter a number (-1 to quit):(12)
(12) is not a number I understand. Enter a number (-1 to quit): -1
These results tell you a few things about the default number format on the platform where I ran it (U.S. English Solaris, JDK 1.1.4). First, it doesn’t understand exponential notation. The square root of 2.998E+8 is not 1.7314733610425546; it’s 1.7314733610425546E+4. The number format parsed up to the first character it didn’t recognize (E) and stopped, thus returning the square root of 2.998 instead. You can also see that this number format doesn’t understand negative numbers represented by parentheses or words like “four.” On the other hand, it can parse numbers with thousands separators like 2,345,678. This is more than the I/O libraries in most other languages can do. With the appropriate, nondefault number format, Java could parse (12), four, and 2.998E+8 as well.
18.220.34.198