引言
在最近的开发中,用到了DecimalFormat这个类来做精度控制的功能。比如想保留两位精度,代码如下:
DecimalFormat decimalFormat = new DecimalFormat("0.##");
decimalFormat.format(12345.2323)
输出结果为:12345.23
掉坑与填坑
使用#和0的区别
对于使用数字"0"格式化,和使用“#”格式化在DecimalFormat中的区别在于:
- "#" 表示有”有效“数字才显示。而使用数字 "0" 则表示在位数不足时或者"无效"时用"0"值补位。
这里的有效和无效指的是数学意义上的有效值。比如0010.2300,有效值为10.23,无效值为千位和百位的0,以及小数点第三位和第四位的0
看以下例子:
DecimalFormat decimalFormat1 = new DecimalFormat("#.##");
DecimalFormat decimalFormat2 = new DecimalFormat("0.00");
System.out.println(decimalFormat1.format(45.2));
System.out.println(decimalFormat1.format(45.20));
System.out.println(decimalFormat2.format(45.2));
System.out.println(decimalFormat2.format(45.20));
System.out.println("******************整数部分测试********************");
DecimalFormat decimalFormat3 = new DecimalFormat("####.00");
DecimalFormat decimalFormat4 = new DecimalFormat("0000.00");
System.out.println(decimalFormat3.format(0.20));
System.out.println(decimalFormat3.format(10.20));
System.out.println(decimalFormat4.format(0.20));
System.out.println(decimalFormat4.format(10.20));
输出为:
******************小数部分测试********************
45.2
45.2
45.20
45.20
******************整数部分测试********************
.20
10.20
0000.20
0010.20
使用除0和#以外的格式符号
对于某些特殊符号,比如“%”会对整体乘以100。或者有时候我们可能需要对格式化后的数据带上前缀或者后缀,比如如果说需求要求格式化的代码如下所示:
DecimalFormat decimalFormat1 = new DecimalFormat("#.##%");
DecimalFormat decimalFormat2 = new DecimalFormat("a0.00");
DecimalFormat decimalFormat3 = new DecimalFormat("负数-0.0");
DecimalFormat decimalFormat4 = new DecimalFormat("上午(0.0am0)");
对于这种情况(不要问我怎么有这种需求),会筛选除“0”和“#”进行格式化,并在整数前面加上前缀,小数后面带后缀,比如上面的输出结果如下所示:
System.out.println(decimalFormat1.format(12.222));
System.out.println(decimalFormat2.format(12.222));
System.out.println(decimalFormat3.format(12.222));
System.out.println(decimalFormat4.format(12.222));
输出结果:
1222.2%
a12.22
负数-12.2
上午(12.22am)
格式化后转换成数值问题
这种问题分两种情况
- 带分隔符的格式化后的数据转换问题
- 语言环境格式化差异带来的数据转换问题
第一种情况比较有可预见性,比如以下代码:
DecimalFormat decimalFormat = new DecimalFormat(",###.##");
//报java.lang.NumberFormatException
Double.valueOf(decimalFormat1.format(12345.2323));
原因是因为格式化的数据变成了“12,345.23”,所以会抛出NumberFormatException。这种情况一般情况下都能考虑到,但是第二种情况就有点坑爹了。看以下代码:
DecimalFormat decimalFormat = new DecimalFormat("#.##");
decimalFormat.format(12345.2323)
就是开头最简单的例子,在中文和英文环境会输出我们预计的结果“12345.23”。
但是!!,在譬如德语等环境下,会输出“12345,23”。原因是因为德语环境下的逗号和点号分隔符的作用是完全相反的。所以如果接下来我们使用了”Double.valueOf()“等转换操作,将会爆出NumberFormatException异常。通过查看DecimalFormat的构造方法:
public DecimalFormat(String pattern) {
// Always applyPattern after the symbols are set
this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
applyPattern(pattern, false);
}
默认是使用当前语言环境作为格式化的符号,因此我们可以手动设置格式化的符号,例如:
DecimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.US));
但是强制使用某种语言环境下的格式化的符号是不可取的,程序中应该针对不同语言环境做不同处理。
网友评论