23. Formatting Numbers
You will have noticed by now that particularly Java double precision numbers often carry an unwieldy number of digits after the decimal point. Java has two classes that allow us to deal with the format that numbers take, and which allow us to manipulate that format into almost any format we desire.
The two classes are java.text.NumberFormat and java.text.DecimalFormat. NumberFormat is an abstract class, i.e. a class which expects to be subclassed so that the subclass can supply the particular details of how exactly the methods of the class should be implemented. DecimalFormat extends NumberFormat and in so doing supplies the detail required by some of the methods of NumberFormat. If you look up these classes in the Java documentation, you will see that they have quite a number of methods. Looking at DecimalFormat will show you that it overrides many of the NumberFormat methods.
Abstract classes are not really in the scope of this tutorial, but the DecimalFormat class has some methods that are very useful in many situations where numbers are being manipulated by classes. We will take a look at how we can set the number of significant digits that follow the decimal point in a number that is a decimal fraction.
DecimalFormat.setMaximumFractionDigits(int newValue) is used to set the maximum number of digits that should follow the decimal point in a decimal fraction. Using this method allows us to format a number in such a way that it will never have more than a fixed number of digits int newValue after the decimal point. However, this method can and often does produce numbers that have less than the maximum number of significant digits after the decimal point. For example, imagine that we wish to format decimal fractions to show 5 significant digits after the decimal point. In a number such as 23.4163224099032 it will be reduced to 23.41632, but in the case of a number such as 3.2479985234066 it will be reduced to 3.248. The reason for this is that in the original number, the 3 digits following the 7 at 3 places after the decimal, are 998. This means that in the process of correctly rounding the reduced length number, the 2nd 9 in 998 becomes a zero because the digit to the right of it is greater than 5 so 1 must be added to this 9 making it 10. The 1 is carried to the 1st 9 in 998, making it a 10 as well, so the 9 becomes a zero and the 1 must be carried to the 7 to the left of the nine. This leaves us with 3.24800 to five significant digits; the two trailing zeros are meaningless and are simply left off the end of the formatted number giving us 3.248.
If we wish to force DecimalFormat to show all the significant digits we requested, we must use the setMinimumFractionDigits(int newValue) method as well, and set int newValue to the same value used for setting the maximum number of digits.
To use the DecimalFormat class we instantiate it and then call the setMaximumFractionDigits(int newValue) method on the instance of the class:
DecimalFormat formatter = new DecimalFormat(); formatter.setMaximumFractionDigits(3); //max 3 decimal digits formatter.setMinimumFractionDigits(3); //force 3 decimal digitsBelow is an example of a class which handles the formatting of decimal fractions using DecimalFormat.
In the image above, the first time TestNumberFormat is run the full 7 decimal digits are forced; in the second they are not.
Note: DecimalFormat.format(double aValue) returns a String not a double! (This is a method inherited from java.text.NumberFormat.) If you want to convert this return value to a number, you will have to use Double.parseDouble(formatter.format(double aNum)).
DecimalFormat also allows us to format numbers according to a specific pattern that we supply. We won't deal with this here, but we encourage you to look up how to do this in the Java documentation for java.text.DecimalFormat.