8.2.13 格式化数值

优质
小牛编辑
133浏览
2023-12-01

本实例演示了如何使用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异常。