Format Specifiers
A printed bill has its prices lined up on the right, always with two decimal places, and item names lined up on the left. You can't get that by joining strings with +. Format specifiers are short codes such as %d and %.2f that tell printf exactly how to show each value: as what type, how wide, and with how many decimals.
The Parts of a Specifier
%[flags][width][.precision]conversion. Only the % and the conversion letter are required.
| Conversion | For | Example | Result |
|---|---|---|---|
%d | Whole numbers (int, long) | printf("%d", 42) | 42 |
%f | Decimals (double, float) | printf("%f", 3.14159) | 3.141590 |
%s | Text, or anything else | printf("%s", "Pune") | Pune |
%c | A char | printf("%c", 'A') | A |
%b | A boolean | printf("%b", true) | true |
%e | Scientific notation | printf("%e", 1234.5) | 1.234500e+03 |
%x | Hexadecimal | printf("%x", 255) | ff |
%n | New line (no value) | printf("Hi%n") | Hi and a new line |
%% | A literal % sign | printf("18%%") | 18% |
Width, Precision and Flags
public class Widths {
public static void main(String[] args) {
System.out.printf("[%d] [%5d] [%-5d] [%05d]%n", 42, 42, 42, 42);
System.out.printf("[%.2f] [%8.2f]%n", 3.14159, 3.14159);
System.out.printf("[%10s] [%-10s]%n", "Pune", "Pune");
System.out.printf("[%,d] [%,.2f]%n", 1234567, 1234567.891);
}
}[42] [ 42] [42 ] [00042]
[3.14] [ 3.14]
[ Pune] [Pune ]
[1,234,567] [1,234,567.89]How it works
- Width
5makes the value take at least 5 characters. Numbers are right-aligned by default:[ 42]. - The
-flag left-aligns:[42 ]. The0flag pads with zeros:[00042]. - Precision
.2means two decimal places:3.14. With width 8, the result is padded to 8 characters. - The
,flag adds grouping separators:1,234,567.
The square brackets aren't part of the format; they're there so you can see the spaces.
Try it yourself: change line 4 to use %.0f and %.4f. What does each print?
A Neat Bill
Width and precision together line up a table:
public class Bill {
public static void main(String[] args) {
String[] items = {"Rice 5 kg", "Toor dal", "Oil 1 L"};
double[] prices = {340.0, 165.5, 189.75};
double total = 0;
for (int i = 0; i < items.length; i++) {
System.out.printf("%-12s Rs. %8.2f%n", items[i], prices[i]);
total += prices[i];
}
System.out.printf("%-12s Rs. %8.2f%n", "Total", total);
}
}Rice 5 kg Rs. 340.00
Toor dal Rs. 165.50
Oil 1 L Rs. 189.75
Total Rs. 695.25%-12s gives every name 12 characters, left-aligned, and %8.2f gives every price 8 characters with 2 decimals, right-aligned, so the decimal points line up. The loop is covered in "Java for Loop".
Rounding and Number Grouping
%.2frounds half up:2.345prints as2.35, and%.0fturns2.5into3.- The
,flag always groups in threes:10,000,000. Java's built-in formatters don't produce Indian lakh and crore grouping (1,00,00,000), even with an Indian locale. You'd need a library such as ICU4J for that. - Grouping and decimal symbols follow the computer's locale. In Germany,
%,.2fgives1.234.567,89. Pass a locale to get the same result everywhere:String.format(Locale.US, "%,.2f", x).
When a Specifier Is Wrong
The compiler doesn't check format strings, so mistakes appear at runtime:
Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.DoubleThat's %d given 5.5: %d needs a whole number. Too few values gives MissingFormatArgumentException. Too many values isn't an error; the extras are ignored.
Common Mistakes
Using %d for a double. Use %f (or %.2f). For a whole number from a double, cast it first: (int) price.
Forgetting %n. Without it, the next output continues on the same line.
Writing % alone for a percent sign. printf("18%") fails; write 18%%.
Practice
- Easy: Print
Pi is about 3.14usingMath.PIand%.2f. - Harder: Print a three-row marks table with the subject name left-aligned in 10 characters and the marks right-aligned in 5, then the percentage with one decimal place.
Key Takeaways
Was this tutorial helpful?