NumberFormat and DecimalFormat in Java

Naveen AnamaneniUpdated · 5 min read

NumberFormat and DecimalFormat, in the java.text package, are used to format numbers as text for people to read, and to parse such text back into numbers. NumberFormat gives ready-made formats for a locale (a country and language): plain numbers with grouping, currencies and percentages. DecimalFormat lets you write your own pattern, such as #,##0.00. In this lesson, you will learn both, and finish with a small program that times a sort and prints the result neatly.

NumberFormat Factory Methods

MethodDescription
NumberFormat.getInstance(locale)It is used to format plain numbers with the locale's grouping.
NumberFormat.getCurrencyInstance(locale)It formats money with the locale's currency symbol.
NumberFormat.getPercentInstance(locale)It formats 0.25 as "25%".
NumberFormat.getCompactNumberInstance(locale, style)It formats 1200 as "1K" (Java 12).
setMaximumFractionDigits(n) / setMinimumFractionDigits(n)It controls the number of decimal places.
parse(String)It turns formatted text back into a Number.

Example: Formatting for Different Locales

Let's see an example that formats the same amount in two locales.

Locales.java▶ Try it
import java.text.NumberFormat;
import java.util.Locale;
 
public class Locales {
    public static void main(String[] args) {
        double amount = 1234567.891;
        Locale india = Locale.of("en", "IN");
 
        System.out.println(
            NumberFormat.getInstance(Locale.US).format(amount));
        System.out.println(
            NumberFormat.getInstance(Locale.GERMANY).format(amount));
        System.out.println(
            NumberFormat.getCurrencyInstance(india).format(amount));
        System.out.println(
            NumberFormat.getCurrencyInstance(Locale.US).format(amount));
        System.out.println(
            NumberFormat.getPercentInstance(Locale.US).format(0.856));
 
        NumberFormat compact = NumberFormat.getCompactNumberInstance(
            Locale.US, NumberFormat.Style.SHORT);
        System.out.println(compact.format(1_250_000));
    }
}
Output
1,234,567.891
1.234.567,891
₹1,234,567.89
$1,234,567.89
86%
1M

Explanation: The US locale uses a comma to group thousands and a dot for decimals; the German locale does the opposite. Currency formats add the right symbol, such as ₹ for India, and round to two decimals. (Java's number formats group digits in threes, so they don't produce the Indian lakh grouping such as 12,34,567.) The percent format multiplies by 100 and rounds. The compact format shortens large numbers.

DecimalFormat Patterns

SymbolMeaning
0A digit, shown even if it's zero
#A digit, hidden if it's a leading or trailing zero
,Grouping separator
.Decimal point
%Multiply by 100 and show as a percentage
'text'Literal text

Example: Custom Patterns

Patterns.java▶ Try it
import java.text.DecimalFormat;
 
public class Patterns {
    public static void main(String[] args) {
        double[] values = {5, 1234.5, 0.756};
 
        DecimalFormat money = new DecimalFormat("#,##0.00");
        DecimalFormat compact = new DecimalFormat("#.##");
        DecimalFormat padded = new DecimalFormat("00000");
        DecimalFormat percent = new DecimalFormat("0.0%");
 
        for (double v : values) {
            System.out.println(money.format(v) + " | " + compact.format(v)
                + " | " + padded.format(v) + " | " + percent.format(v));
        }
    }
}
Output
5.00 | 5 | 00005 | 500.0%
1,234.50 | 1234.5 | 01234 | 123450.0%
0.76 | 0.76 | 00001 | 75.6%

Explanation: #,##0.00 always shows two decimals and groups thousands. #.## shows up to two decimals and drops trailing zeros. 00000 pads to five digits (rounding 1234.5 to the even neighbor, 1234, and 0.756 up to 1). 0.0% multiplies by 100.

The Checkpoint: Timing a Sort

This program times sorting arrays of different sizes with System.nanoTime and prints the results with DecimalFormat. Times depend on the computer, so the output is a sample.

SortTimer.java▶ Try it
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Random;
 
public class SortTimer {
    public static void main(String[] args) {
        DecimalFormat count = new DecimalFormat("#,##0");
        DecimalFormat millis = new DecimalFormat("0.00");
        Random random = new Random(1);
 
        for (int size : new int[] {10_000, 100_000, 1_000_000}) {
            int[] data = random.ints(size).toArray();
            long start = System.nanoTime();
            Arrays.sort(data);
            double ms = (System.nanoTime() - start) / 1_000_000.0;
            System.out.println("Sorted " + count.format(size)
                + " numbers in " + millis.format(ms) + " ms");
        }
    }
}
Output
Sorted 10,000 numbers in 2.96 ms
Sorted 100,000 numbers in 5.66 ms
Sorted 1,000,000 numbers in 44.42 ms

Explanation: For each size, a seeded Random fills an array, nanoTime is read before and after Arrays.sort, and the difference is converted to milliseconds. #,##0 adds grouping to the counts, and 0.00 shows exactly two decimals for the times.

Common Mistakes

Formatting money with double arithmetic. Calculate with BigDecimal, then format.

Sharing one DecimalFormat between threads. It isn't thread-safe; create one per thread or per use.

Forgetting the locale. The output then depends on the computer's settings.

Practice

  1. Easy: Print a list of product prices as Indian rupee amounts using getCurrencyInstance(Locale.of("en", "IN")).
  2. Harder: Parse the text "1,234,567.50" with an Indian NumberFormat, add 10%, and print it again in the same format.

Quick check: NumberFormat and DecimalFormat

4 questions
1Which class gives locale-aware currency formats?
2In a DecimalFormat pattern, what does 0 mean?
3What does new DecimalFormat("0.0%").format(0.25) give?
4Is DecimalFormat thread-safe?

Key Takeaways

Was this tutorial helpful?

Lesson 339 of 482