如何使用 DecimalFormat 设置数字的千分位分隔符及小数点掩码?
- 内容介绍
- 相关推荐
本文共计742个文字,预计阅读时间需要3分钟。
直接生效的方式是使用带有占位符的+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分钟。
直接生效的方式是使用带有占位符的+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。

