8.2.13 格式化数值
本实例演示了如何使用NumberFormat对象格式化数值、货币和百分数,以及将格式化数值后的字符串追加到其他的字符串后面,并使用FieldPosition对象跟踪追加的位置,最后演示了DecimalFormat对象如何通过模式字符串来格式化数值。
例子 : 格式化数值
1. 编写FormatNumber程序
FormatNumber类演示了各种格式化数值操作,该类的代码如下:
package chapter8;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.util.Locale;
public class FormatNumber
{
public static void main(String[] args) throws Exception
{
NumberFormat nf1 = NumberFormat.getInstance();
System.out.print("使用组分隔符格式化数值:");
System.out.println(nf1.format(1234.56));
nf1.setGroupingUsed(false);
System.out.print("不使用组分隔符格式化数值:");
System.out.println(nf1.format(1234.56));
NumberFormat nf2 = NumberFormat.getCurrencyInstance(Locale.US);
System.out.print("使用处理货币的NumberFormat对象格式化数值:");
System.out.println(nf2.format(20.5));
System.out.print("使用处理百分数的NumberFormat对象格式化数值:");
NumberFormat nf3 = NumberFormat.getPercentInstance();
// 小数部分的最小位数指定的百分数的小数部分
nf3.setMinimumFractionDigits(2);
System.out.println(nf3.format(0.356));
// 将格式化后的结果追加到字符串后面,并跟踪追加的位置
FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
StringBuffer sb = new StringBuffer("数学测试的合格率为:");
String numberString = nf3.format(0.965, sb, fp).toString();
System.out.println(numberString);
System.out.println("追加百分数的整数部分的开始位置是" + fp.getBeginIndex()
+ " 整数部分后的第一个字符的位置是" + fp.getEndIndex());
// 将nf2转换为DecimalFormat对象
DecimalFormat df = (DecimalFormat) nf2;
// 小数部分至少是2位数字
df.applyPattern("0.00");
System.out.println("小数部分不足2位数字,补0:" + df.format(12.5));
System.out.println("小数部分超过2位数字,截取多余部分:" + df.format(12.5678));
// 小数部分至少是1位数字,最多是3位数字
df.applyPattern("0.0##");
System.out.println("小数部分不足1位数字,补0:" + df.format(12));
System.out.println("小数部分超过3位数字,截取多余部分:" + df.format(12.5678));
// 整数部分至少是3位数字,小数部分至少是2位数字
df.applyPattern("000.00");
System.out.println("整数部分不足3位数字,补0:" + df.format(12.1));
System.out.println("整数部分超过3位数字,按原样返回:" + df.format(1234.1));
}
}
2. 测试FormatNumber程序
运行FormatNumber程序后,将输出如下的结果:
使用组分隔符格式化数值:1,234.56
不使用组分隔符格式化数值:1234.56
使用处理货币的NumberFormat对象格式化数值:$20.50
使用处理百分数的NumberFormat对象格式化数值:35.60%
数学测试的合格率为:96.50%
追加百分数的整数部分的开始位置是10 整数部分后的第一个字符的位置是12
小数部分不足2位数字,补0:12.50
小数部分超过2位数字,截取多余部分:12.57
小数部分不足1位数字,补0:12.0
小数部分超过3位数字,截取多余部分:12.568
整数部分不足3位数字,补0:012.10
整数部分超过3位数字,按原样返回:1234.10
3. 程序总结
在上面的程序中使用了用户自定义的模式字符串,在模式字符串中涉及到了“#”和“0”。这两个模式符号都表示1位数字,但将其用在小数和整数部分有着不同的含义。这些含义如下:
l 如果将“0”和“#”用在小数部分,则表示小数点后可有的最多位数。如“0.00”和“0.0#”都表示小数点后最多可有2位数字。如果小数点后的数字超过2位,则只保留前两位,并且遵循四舍五入的原则。如“1.123”经过格式化后变为“1.12”,而“1.126”经过格式化后变为“1.13”。
2 虽然“0”和“#”在小数部分都可以表示数字的位数。但如果将“0”用在小数部分,当小数点后的数字位数不到最大位数,则后面补0,如果将“#”用在小数部分,当小数点后的数字位数小于最大位数,并不会补0,而是按原样格式化。如用格式化字符串“0.00”格式化“1.4”,最终的结果是“1.40”。而且“0.0#”格式化“1.4”,最终的结果仍然是“1.4”。
3 如果将“0”用在整数部分,也表示整数部分的数字位数,但不是最大的数字位数,而是实际的数字位数小于最大位数时,前面补0,如果实际的数字位数超过最大位数,则按原样输出。如用格式化字符串“000.0”格式化“12.1”,输出结果是“012.1”,而格式化“12345.2”的输出结果仍然为“12345.2”。
4 如果将“#”用在整数部分既不会起到限制数字位数的作用(使用setMaximumIntegerDigits方法设置的整数部分最大位数则会从高位截取多余的位数,详见8.2.10节的内容),也不会起到补0的作用。但“#”和“0”都会被当作1位数字,因此,可以使用混合“0”或“#”来格式化数值的输出方式。如“#,###.0”表示输出的数值的小数部分最多只能有一位数字,而且如果整数部分超过3位数字,则每3位数字使用逗号(,)分隔。如格式化“12345.41”的输出结果是“12,345.4”。
5 如果“0”和“#”被混合用在整数部分,“0”必须跟在“#”序列的最后,如果“0”和“#”被混合用在小数部分,“0”必须放在“#”序列的开始部分。而且“0”和“#”不能交替使用。如“##0.00##”、“#00.0##”都是合法的,而“0##.#00”、“#0##.0#0"都是非法的格式化字符串。如果使用这些格式化字符串将抛出java.lang.IllegalArgumentException异常。