首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 數字格式化完全指南:DecimalFormat 與 NumberFormat 實戰詳解

     編輯:Java 相關知識

前言

數字格式化是國際化應用的核心需求。Java 提供 NumberFormat 抽象層與 DecimalFormat 具體實作,支援區域敏感的數字、貨幣、百分比、科學記號格式化與解析。本文系統整理核心 API、常見模式、區域化處理與最佳實務。

核心類別架構

NumberFormat (abstract)
├── DecimalFormat          // 數字/貨幣/百分比/科學記號
├── ChoiceFormat           // 區間對應格式
└── CompactNumberFormat    // Java 12+ 簡潔格式 (1.2K, 3.4M)

建立格式化器的三種方式


// 1. 取得預設區域的數字格式化器(實為 DecimalFormat)
NumberFormat nf = NumberFormat.getInstance();           // 一般數字
NumberFormat cf = NumberFormat.getCurrencyInstance();   // 貨幣
NumberFormat pf = NumberFormat.getPercentInstance();    // 百分比

// 2. 指定 Locale(跨區域顯示)
NumberFormat deFormat = NumberFormat.getInstance(Locale.GERMANY); // 1.234,56
NumberFormat usFormat = NumberFormat.getInstance(Locale.US);      // 1,234.56

// 3. 直接使用 DecimalFormat 完全控制模式
DecimalFormat df = new DecimalFormat("#,##0.00");       // 模式字串
DecimalFormat df2 = (DecimalFormat) NumberFormat.getInstance(Locale.TAIWAN);
df2.applyPattern("#,##0.00"); // 結合區域預設與自訂模式

DecimalFormat 模式符號完整對照表

符號含義範例輸入範例輸出
0數字,不足補 0new DecimalFormat("0.00").format(1.2)1.20
#數字,不足不補new DecimalFormat("#.##").format(1.2)1.2
.小數點(依區域轉換)DE: 1.234,56 | US: 1,234.56-
,分組分隔符(依區域轉換)df.setGroupingSize(3)1,234,567
%百分比(乘 100 加 %)new DecimalFormat("##.0%").format(0.123)12.3%
E科學記號new DecimalFormat("0.00E0").format(1234)1.23E3
¤貨幣符號new DecimalFormat("¤#,##0.00").format(1234.5)NT$1,234.50
'text'字面文字new DecimalFormat("'Year:' yyyy").format(...)-

常見格式化場景實戰

1. 固定小數位數

DecimalFormat df = new DecimalFormat("0.00"); // 強制兩位小數
System.out.println(df.format(1.2));    // 1.20
System.out.println(df.format(1.234));  // 1.23 (四捨五入)
System.out.println(df.format(1));      // 1.00

2. 百分比格式化

// 方式一:模式含 %
DecimalFormat pct1 = new DecimalFormat("##.00%");
System.out.println(pct1.format(0.1234)); // 12.34%
System.out.println(pct1.format(1.0));    // 100.00%

// 方式二:手動乘 100 + 加號
DecimalFormat pct2 = new DecimalFormat("##.00");
System.out.println(pct2.format(0.1234 * 100) + "%"); // 12.34%

3. 千分位分組與自訂分組大小

DecimalFormat df = new DecimalFormat("#,###");
df.setGroupingSize(3); // 標準三位一撇
System.out.println(df.format(123456789)); // 123,456,789

// 印度計數法:萬/億分組 (3,2,2...)
df.setGroupingSize(2); // 僅作示範,實際需更複雜邏輯
System.out.println(df.format(123456789)); // 1,23,45,67,89

// 禁用分組
df.setGroupingUsed(false);
System.out.println(df.format(123456789)); // 123456789

4. 貨幣格式化(含貨幣符號、小數位、區域)

NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.TAIWAN);
System.out.println(currency.format(1234567.89)); // NT$1,234,568

// 精確控制:不四捨五入分
DecimalFormat currencyDf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
currencyDf.setMaximumFractionDigits(2);
currencyDf.setMinimumFractionDigits(2);
currencyDf.setRoundingMode(RoundingMode.DOWN); // 截斷不進位
System.out.println(currencyDf.format(123.456)); // $123.45

5. 科學記號

DecimalFormat sci = new DecimalFormat("0.00E00");
System.out.println(sci.format(12345));    // 1.23E04
System.out.println(sci.format(0.00123));  // 1.23E-03

解析:字串轉數字

NumberFormat nf = NumberFormat.getInstance(Locale.GERMANY);
try {
    Number num = nf.parse("1.234,56"); // 德式:點分組、逗號小數
    System.out.println(num.doubleValue()); // 1234.56
    System.out.println(num.getClass());    // java.lang.Double
} catch (ParseException e) {
    e.printStackTrace();
}

// 解析為特定型別
Long l = nf.parse("1234", new ParsePosition(0)).longValue();

區域化實戰:同一數字在不同 Locale 顯示


double value = 1234567.891;
Locale[] locales = {Locale.US, Locale.GERMANY, Locale.TAIWAN, Locale.CHINA, Locale.JAPAN};

for (Locale loc : locales) {
    NumberFormat nf = NumberFormat.getInstance(loc);
    NumberFormat cf = NumberFormat.getCurrencyInstance(loc);
    NumberFormat pf = NumberFormat.getPercentInstance(loc);
    
    System.out.printf("%-10s | 數字: %-20s | 貨幣: %-20s | 百分比: %s%n",
        loc.getDisplayName(), nf.format(value), cf.format(value), pf.format(0.1234));
}

輸出範例:

美國       | 數字: 1,234,567.891    | 貨幣: $1,234,567.89    | 百分比: 12%
德國       | 數字: 1.234.567,891    | 貨幣: 1.234.567,89 €   | 百分比: 12%
台灣       | 數字: 1,234,567.891    | 貨幣: NT$1,234,568     | 百分比: 12%
中國       | 數字: 1,234,567.891    | 貨幣: ¥1,234,567.89   | 百分比: 12%
日本       | 數字: 1,234,567.891    | 貨幣: ¥1,234,568      | 百分比: 12%

進階技巧與最佳實務

1. 執行緒安全

DecimalFormat 非執行緒安全。多執行緒環境下:

  • 方法區域變數建立實例(推薦)
  • 使用 ThreadLocal<DecimalFormat> 快取
  • 或同步區塊 synchronized(df)

2. 效能優化:重用與預編譯


// 不好:每次新建
String s = new DecimalFormat("#,##0.00").format(value);

// 好:靜態常數重用(單執行緒/請求範圍)
private static final DecimalFormat PRICE_FORMAT = new DecimalFormat("#,##0.00");
String s = PRICE_FORMAT.format(value);

3. 避免浮點數精度陷阱


// 錯誤
double price = 19.99;
System.out.println(new DecimalFormat("0.00").format(price * 0.1)); // 1.999 → 2.00

// 正確:使用 BigDecimal
BigDecimal price = new BigDecimal("19.99");
BigDecimal discount = price.multiply(new BigDecimal("0.1"));
System.out.println(new DecimalFormat("0.00").format(discount)); // 2.00

4. Java 12+ CompactNumberFormat 簡潔格式


NumberFormat compact = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
System.out.println(compact.format(1234));      // 1.2K
System.out.println(compact.format(1234567));   // 1.2M
System.out.println(compact.format(1234567890)); // 1.2B

總結

掌握 DecimalFormat 模式語法、區域化行為、解析邏輯與執行緒安全陷阱,是處理金融、報表、國際化顯示的基本功。建立專案共用的 FormatUtils 統一管理格式化器實例,搭配 BigDecimal 進行精確計算,可避免 90% 的數字顯示與計算錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved