處理金融、科學計算時,「保留 N 位小數」 是高頻需求。本文以 NumberFormat 為核心,示範標準實作,並說明為何不建議直接用 BigDecimal 或 String.format 的常見誤區。
NumberFormat.getNumberInstance()import java.text.NumberFormat;
public class DecimalUtils {
/**
* 保留指定小數位數(四捨五入)
*
* @param number 目標數值
* @param digits 保留位數(>=0)
* @return 格式化後的 double
*/
public static double saveNumber(double number, int digits) {
if (digits < 0) throw new IllegalArgumentException("digits must be >= 0");
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(digits); // 關鍵:設定最大小數位
nf.setMinimumFractionDigits(digits); // 可選:強制補齊位數(如 1.5 → 1.50)
nf.setGroupingUsed(false); // 關閉千分位分隔符(避免 1,234.56)
String formatted = nf.format(number);
return Double.parseDouble(formatted);
}
}
| 方法 | 作用 | 建議值 |
|---|---|---|
setMaximumFractionDigits(int) |
最大小數位(超過則四捨五入) | 業務需求位數 |
setMinimumFractionDigits(int) |
最小小數位(不足補 0) | 同最大位數(金融常用) |
setGroupingUsed(boolean) |
是否啟用千分位分隔符 | false(避免解析錯誤) |
setRoundingMode(RoundingMode) |
指定捨入模式 | RoundingMode.HALF_UP(預設) |
BigDecimal.setScale 直接回傳 double// 危險:double 二進制精度缺失,1.005 可能變 1.00
double d = new BigDecimal("1.005").setScale(2, RoundingMode.HALF_UP).doubleValue();
String.format("%.2f", num)String,後續計算需再轉型NumberFormat + Locale 明確控制NumberFormat nf = NumberFormat.getNumberInstance(Locale.US); // 強制點號作小數點
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
nf.setGroupingUsed(false);
double result = Double.parseDouble(nf.format(1234.567)); // 1234.57
public class Test {
public static void main(String[] args) {
System.out.println(DecimalUtils.saveNumber(15.12312312, 6)); // 15.123123
System.out.println(DecimalUtils.saveNumber(100.005, 2)); // 100.01
System.out.println(DecimalUtils.saveNumber(3.1, 4)); // 3.1000
}
}
NumberFormat 而非 String.format 或 BigDecimal.doubleValue()GroupingUsed 並明確設定 LocaleBigDecimal 運算,僅在最後輸出時格式化