如何使用 DecimalFormat 设置数字的千分位分隔符及小数点掩码?

2026-04-29 08:551阅读0评论SEO资讯
  • 内容介绍
  • 相关推荐

本文共计742个文字,预计阅读时间需要3分钟。

如何使用 DecimalFormat 设置数字的千分位分隔符及小数点掩码?

直接生效的方式是使用带有占位符的+pattern+字符串构造,例如:

setGroupingUsed(true) 和 pattern 里的 , 不是互斥关系

如果你用无参构造器创建 DecimalFormat,再调用 setGroupingUsed(true),它只会启用默认分组(如英文 locale 下用逗号),但不会自动加小数位控制或指定分隔符字符。真正决定“是否分组”“用什么符号分组”“小数点后几位”的,还是 pattern 字符串本身。所以更稳妥的做法是:直接写完整 pattern,避免依赖 locale 或后续 setter 调用顺序。

  • new DecimalFormat("#,###") → 整数部分分组,无小数
  • new DecimalFormat("0,000.00") → 强制整数至少 4 位(不足补零),小数固定两位
  • new DecimalFormat("#,##0.##") → 整数部分分组,小数最多两位(末尾零不显示)

想换千分位符号?别改 pattern,改 DecimalFormatSymbols

pattern 里的 , 只是个占位指令,实际渲染成什么字符(逗号、点、空格、甚至竖线),由 DecimalFormatSymbols 控制。比如欧洲地区常用 . 做千分位、, 做小数点,这时不能硬改 pattern 为 "#.###,#"——那是错的,会解析失败。正确做法是:

  • 新建 DecimalFormatSymbols 实例,调用 setGroupingSeparator(' ')setGroupingSeparator('\u00a0')(窄空格)
  • 把该 symbols 传给 DecimalFormat 构造器:new DecimalFormat("#,###.00", symbols)
  • 小数点符号同理:setDecimalSeparator(',')

否则仅靠 pattern,你永远无法把千分位改成中文顿号、斜杠或自定义字符。

常见踩坑:四舍五入行为、负数、locale 隐式影响

format() 默认使用 RoundingMode.HALF_EVEN(银行家舍入),不是简单四舍五入。如果业务要求明确向上/向下取整,必须显式设置:df.setRoundingMode(RoundingMode.HALF_UP)

  • 负数默认带前导 -,pattern 中加 '-' 无法改变;如需括号表示(如 (123.45)),得用 "(#,###.00);(#,###.00)" 这种双模式
  • 不指定 DecimalFormatSymbols 时,DecimalFormat 会按当前 Locale.getDefault() 解析 pattern 中的符号含义——比如在德语环境,"#,###.00" 可能被当作“小数点用逗号”,导致异常
  • pattern 中出现非法字符(如未转义的单引号、多余小数点)会抛 IllegalArgumentException

最易被忽略的是:pattern 一旦传入构造器,后续调用 applyPattern() 会重置所有符号配置(包括自定义的 grouping/decimal separator),必须重新 setSymbols。

本文共计742个文字,预计阅读时间需要3分钟。

如何使用 DecimalFormat 设置数字的千分位分隔符及小数点掩码?

直接生效的方式是使用带有占位符的+pattern+字符串构造,例如:

setGroupingUsed(true) 和 pattern 里的 , 不是互斥关系

如果你用无参构造器创建 DecimalFormat,再调用 setGroupingUsed(true),它只会启用默认分组(如英文 locale 下用逗号),但不会自动加小数位控制或指定分隔符字符。真正决定“是否分组”“用什么符号分组”“小数点后几位”的,还是 pattern 字符串本身。所以更稳妥的做法是:直接写完整 pattern,避免依赖 locale 或后续 setter 调用顺序。

  • new DecimalFormat("#,###") → 整数部分分组,无小数
  • new DecimalFormat("0,000.00") → 强制整数至少 4 位(不足补零),小数固定两位
  • new DecimalFormat("#,##0.##") → 整数部分分组,小数最多两位(末尾零不显示)

想换千分位符号?别改 pattern,改 DecimalFormatSymbols

pattern 里的 , 只是个占位指令,实际渲染成什么字符(逗号、点、空格、甚至竖线),由 DecimalFormatSymbols 控制。比如欧洲地区常用 . 做千分位、, 做小数点,这时不能硬改 pattern 为 "#.###,#"——那是错的,会解析失败。正确做法是:

  • 新建 DecimalFormatSymbols 实例,调用 setGroupingSeparator(' ')setGroupingSeparator('\u00a0')(窄空格)
  • 把该 symbols 传给 DecimalFormat 构造器:new DecimalFormat("#,###.00", symbols)
  • 小数点符号同理:setDecimalSeparator(',')

否则仅靠 pattern,你永远无法把千分位改成中文顿号、斜杠或自定义字符。

常见踩坑:四舍五入行为、负数、locale 隐式影响

format() 默认使用 RoundingMode.HALF_EVEN(银行家舍入),不是简单四舍五入。如果业务要求明确向上/向下取整,必须显式设置:df.setRoundingMode(RoundingMode.HALF_UP)

  • 负数默认带前导 -,pattern 中加 '-' 无法改变;如需括号表示(如 (123.45)),得用 "(#,###.00);(#,###.00)" 这种双模式
  • 不指定 DecimalFormatSymbols 时,DecimalFormat 会按当前 Locale.getDefault() 解析 pattern 中的符号含义——比如在德语环境,"#,###.00" 可能被当作“小数点用逗号”,导致异常
  • pattern 中出现非法字符(如未转义的单引号、多余小数点)会抛 IllegalArgumentException

最易被忽略的是:pattern 一旦传入构造器,后续调用 applyPattern() 会重置所有符号配置(包括自定义的 grouping/decimal separator),必须重新 setSymbols。