NumberFormat and printf
Format numbers for display using NumberFormat, DecimalFormat, and printf patterns.
NumberFormat and printf is a free Java Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
NumberFormat and printf
Java provides rich number formatting APIs: NumberFormat for locale-aware currency/percent, DecimalFormat for custom patterns, and printf/String.format for C-style formatting.
String.format Basics
String.format() uses format specifiers to build strings. Common specifiers: %d (integer), %f (float), %s (string), %n (newline).
String name = "Alice";
int score = 95;
double avg = 87.567;
String msg = String.format(
"Player: %s | Score: %d | Average: %.2f", name, score, avg);
System.out.println(msg);
// Player: Alice | Score: 95 | Average: 87.57
// printf is equivalent — formats directly to output
System.out.printf("%-10s %5d %8.2f%n", name, score, avg);
// Alice 95 87.57Width, Padding, and Alignment
Format specifiers support width and alignment flags: %10d (right-align in 10 chars), %-10d (left-align), %010d (zero-pad).
// Table layout with padding
System.out.printf("%-20s %10s %10s%n", "Product", "Qty", "Price");
System.out.printf("%-20s %10d %10.2f%n", "Java Book", 3, 49.99);
System.out.printf("%-20s %10d %10.2f%n", "USB Hub", 1, 24.95);
System.out.printf("%-20s %10d %10.2f%n", "Mechanical Keyboard", 2, 129.00);
// Zero-padding for order IDs
int orderId = 42;
System.out.printf("Order: ORD-%08d%n", orderId); // Order: ORD-00000042NumberFormat for Currency
NumberFormat.getCurrencyInstance(Locale) formats numbers as currency strings with the correct symbol, separators, and decimal places for a given locale.
import java.text.*;
import java.util.*;
NumberFormat usd = NumberFormat.getCurrencyInstance(Locale.US);
NumberFormat eur = NumberFormat.getCurrencyInstance(Locale.GERMANY);
NumberFormat gbp = NumberFormat.getCurrencyInstance(Locale.UK);
double amount = 1234567.89;
System.out.println(usd.format(amount)); // $1,234,567.89
System.out.println(eur.format(amount)); // 1.234.567,89 EUR
System.out.println(gbp.format(amount)); // GBP1,234,567.89NumberFormat for Percentages
NumberFormat.getPercentInstance() formats a decimal as a percentage string. Pass a value between 0 and 1.
import java.text.*;
import java.util.*;
NumberFormat pct = NumberFormat.getPercentInstance(Locale.US);
pct.setMaximumFractionDigits(1);
System.out.println(pct.format(0.75)); // 75%
System.out.println(pct.format(0.1234)); // 12.3%
System.out.println(pct.format(1.0)); // 100%
// Conversion rate in e-commerce
double convRate = 3_456.0 / 42_000.0;
System.out.println("Conversion: " + pct.format(convRate)); // 8.2%DecimalFormat with Custom Patterns
DecimalFormat uses a pattern string where # means optional digit and 0 means mandatory digit.
import java.text.*;
DecimalFormat df1 = new DecimalFormat("#,###.00");
System.out.println(df1.format(1234567.5)); // 1,234,567.50
DecimalFormat df2 = new DecimalFormat("000.0");
System.out.println(df2.format(7.5)); // 007.5
DecimalFormat df3 = new DecimalFormat("0.00E0");
System.out.println(df3.format(0.000123)); // 1.23E-4
// Scientific notation for large values
DecimalFormat sci = new DecimalFormat("0.000E0");
System.out.println(sci.format(123456789)); // 1.235E8Parsing Numbers from Strings
NumberFormat can also parse locale-formatted strings back to numbers. This is essential for reading user input in different locales.
import java.text.*;
import java.util.*;
NumberFormat nf = NumberFormat.getInstance(Locale.GERMANY);
try {
// German uses comma as decimal separator
Number parsed = nf.parse("1.234,56");
System.out.println(parsed.doubleValue()); // 1234.56
// Parse US currency string
NumberFormat usd = NumberFormat.getCurrencyInstance(Locale.US);
Number amount = usd.parse("$1,234.56");
System.out.println(amount.doubleValue()); // 1234.56
} catch (ParseException e) {
System.out.println("Parse error: " + e.getMessage());
}Formatted Strings (Java 15+)
Java 15+ adds String.formatted() as an instance method alternative to String.format(), useful in method chains and stream pipelines.
record Product(String name, double price, int stock) {}
var products = List.of(
new Product("Laptop", 999.0, 5),
new Product("Mouse", 29.99, 42),
new Product("Monitor", 349.0, 8)
);
products.stream()
.map(p -> "%-15s $%8.2f [stock: %d]"
.formatted(p.name(), p.price(), p.stock()))
.forEach(System.out::println);
// Laptop $ 999.00 [stock: 5]
// Mouse $ 29.99 [stock: 42]
// Monitor $ 349.00 [stock: 8]Number Grouping and Locale
Number grouping (thousands separator) varies by locale. Always use NumberFormat for user-facing output rather than hardcoding commas.
import java.text.*;
import java.util.*;
long users = 1_234_567;
for (Locale locale : new Locale[]{Locale.US, Locale.FRANCE, Locale.GERMANY}) {
NumberFormat nf = NumberFormat.getIntegerInstance(locale);
System.out.printf("%-10s: %s%n", locale, nf.format(users));
}
// en_US : 1,234,567
// fr_FR : 1 234 567
// de_DE : 1.234.567Invoice Generation Example
Putting it together: generating a formatted invoice printout with proper currency, percentage, and table alignment.
import java.text.*;
import java.util.*;
NumberFormat curr = NumberFormat.getCurrencyInstance(Locale.US);
NumberFormat pct = NumberFormat.getPercentInstance();
pct.setMaximumFractionDigits(0);
double subtotal = 1259.97;
double discount = 0.10;
double discountAmt = subtotal * discount;
double taxRate = 0.08;
double taxAmt = (subtotal - discountAmt) * taxRate;
double total = subtotal - discountAmt + taxAmt;
System.out.println("=== INVOICE ===");
System.out.printf("%-20s %15s%n", "Subtotal", curr.format(subtotal));
System.out.printf("%-20s %15s%n", "Discount (" + pct.format(discount) + ")",
"-" + curr.format(discountAmt));
System.out.printf("%-20s %15s%n", "Tax (" + pct.format(taxRate) + ")",
curr.format(taxAmt));
System.out.printf("%-20s %15s%n", "TOTAL", curr.format(total));Common Pitfalls
Watch out for these common formatting mistakes:
- Using
String.formatwith wrong type specifier (e.g.,%dfor adouble) throwsIllegalFormatConversionException - Locale-specific formatters produce different output on different machines
- NumberFormat instances are not thread-safe — create one per thread or use
ThreadLocal
// Wrong specifier
try {
String.format("%d", 3.14); // IllegalFormatConversionException
} catch (java.util.IllegalFormatConversionException e) {
System.out.println("Wrong format specifier!");
}
// Thread-safe pattern using ThreadLocal
ThreadLocal<NumberFormat> localFmt = ThreadLocal
.withInitial(() -> NumberFormat.getCurrencyInstance(Locale.US));
// each thread gets its own NumberFormat instanceQuick Check
What does String.format("%08.2f", 3.5) produce?
Recap: NumberFormat and printf
Key takeaways:
- String.format / printf use format specifiers: %d, %f, %s, %.2f
- Width and alignment flags: %10d (right), %-10d (left), %010d (zero-pad)
- NumberFormat.getCurrencyInstance() for locale-aware currency display
- NumberFormat.getPercentInstance() for percentage output
- DecimalFormat uses # (optional) and 0 (mandatory) digit patterns
- NumberFormat can also parse locale-formatted strings back to numbers
Frequently asked questions
Is the “NumberFormat and printf” lesson free?
Yes — the full text of “NumberFormat and printf” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “NumberFormat and printf”?
Format numbers for display using NumberFormat, DecimalFormat, and printf patterns. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “NumberFormat and printf” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Math Class Essentials
- Integer Arithmetic & Overflow
- BigDecimal for Financial Calculations
- NumberFormat and printf