I have the following code:
public class Main {
public static void main(String[] args) {
String pattern = ".00"; // a) => |.46|
// String pattern = ".##"; // b) => |.46|
// String pattern = ".0#"; // c) => |.46|
// String pattern = "#.00"; // d) => |.46|
// String pattern = "#.0#"; // e) => |.46|
// String pattern = "#.##"; // f) => |0.46|
// String pattern = ".#0"; // g) => IllegalArgumentException: Malformed pattern ".#0"
double value = 0.456;
DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);
df.applyPattern(pattern);
String output = df.format(value);
System.out.printf("|%s|", output);
}
}
Could someone explain that why in f) the zero before decimal point still displays while d) and e) don't even though they are all have a '#' before decimal point in the pattern? Also, what could be the reason for the exception in g) as it seems to me a valid pattern?
In case "f", the zero shows up because Java prints a 0
if it's not guaranteed that there is a fraction part to print. The below code is taken from JDK 17 source code for DecimalFormat
. Because you have all #
after the decimal point, minFraDigits
is 0
so it can't assume that a fraction is present. It apparently doesn't see that there is a fraction part to print yet. It guards against printing nothing if the value is zero.
// Determine whether or not there are any printable fractional
// digits. If we've used up the digits we know there aren't.
boolean fractionPresent = (minFraDigits > 0) ||
(!isInteger && digitIndex < digitList.count);
// If there is no fraction present, and we haven't printed any
// integer digits, then print a zero. Otherwise we won't print
// _any_ digits, and we won't be able to parse this string.
if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
result.append(zero);
}
The case "g" format is an invalid format. You can't have a 0
further from the decimal point than a #
. It's enforced in the
parsing grammar in the DecimalFormat
javadocs. For the
Fraction part, the zeros must come first if they exist, followed by
optional #
s.
Fraction:
MinimumFractionopt OptionalFractionoptMinimumFraction:
0 MinimumFractionoptOptionalFraction:
# OptionalFractionopt
Another part of the grammar similar to this enforces that before the decimal point, any #
s must be before any 0
s, the reverse of after the decimal point.