# 格式化数字打印输出

> 原文： [https://docs.oracle.com/javase/tutorial/java/data/numberformat.html](https://docs.oracle.com/javase/tutorial/java/data/numberformat.html)

之前您已经看到使用`print`和`println`方法将字符串打印到标准输出（`System.out`）。由于所有数字都可以转换为字符串（您将在本课后面看到），因此您可以使用这些方法打印出字符串和数字的任意混合。但是，Java 编程语言还有其他方法，可以在包含数字时对打印输出进行更多控制。

## printf 和格式方法

`java.io`包中包含`PrintStream`类，它有两种格式化方法可用于替换`print`和`println`。这些方法`format`和`printf`彼此相同。您一直使用的熟悉的`System.out`恰好是`PrintStream`对象，因此您可以在`System.out`上调用`PrintStream`方法。因此，您可以在您之前使用过`print`或`println`的代码中的任何位置使用`format`或`printf`。例如，

```
System.out.format(.....);

```

这两个 [`java.io.PrintStream`](https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html) 方法的语法是相同的：

```
public PrintStream format(String format, Object... args)

```

其中`format`是指定要使用的格式的字符串，`args`是使用该格式打印的变量列表。一个简单的例子就是

```
System.out.format("The value of " + "the float variable is " +
     "%f, while the value of the " + "integer variable is %d, " +
     "and the string is %s", floatVar, intVar, stringVar); 

```

第一个参数`format`是一个格式字符串，指定如何格式化第二个参数`args`中的对象。格式字符串包含纯文本以及 _ 格式说明符 _，它们是格式化`Object... args`参数的特殊字符。 （符号`Object... args`称为 _varargs_ ，这意味着参数的数量可能会有所不同。）

格式说明符以百分号（％）开头，以 _ 转换器 _ 结束。转换器是一个字符，指示要格式化的参数类型。在百分号（％）和转换器之间，您可以使用可选的标志和说明符。有许多转换器，标志和说明符，在 [`java.util.Formatter`](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html) 中有记录

这是一个基本的例子：

```
int i = 461012;
System.out.format("The value of i is: %d%n", i);

```

`%d`指定单个变量是十进制整数。 `%n`是与平台无关的换行符。输出是：

```
The value of i is: 461012

```

`printf`和`format`方法过载。每个版本都有一个具有以下语法的版本：

```
public PrintStream format(Locale l, String format, Object... args)

```

例如，要在法语系统中打印数字（使用逗号代替浮点数的英文表示中的小数位），您将使用：

```
System.out.format(Locale.FRANCE,
    "The value of the float " + "variable is %f, while the " +
    "value of the integer variable " + "is %d, and the string is %s%n", 
    floatVar, intVar, stringVar); 

```

## 一个例子

下表列出了表格后面的示例程序`TestFormat.java`中使用的一些转换器和标志。

<caption style="font-weight: bold">Converters and Flags Used in `TestFormat.java`</caption>
| 变流器 | 旗 | 说明 |
| --- | --- | --- |
| d |  | 十进制整数。 |
| F |  | 一个浮子。 |
| ñ |  | 适合运行应用程序的平台的新行字符。您应该始终使用`%n`，而不是`\n`。 |
| 结核病 |  | 约会和日期时间转换 - 特定于语言环境的月份全名。 |
| td，te |  | 约会和;时间转换 - 每月 2 位数的日期。 td 根据需要有前导零，te 没有。 |
| ty，tY |  | 约会和日期时间转换-ty = 2 位数年份，tY = 4 位数年份。 |
| TL |  | 约会和日期 12 小时制的时间转换小时。 |
| Tm 值 |  | 约会和;时间转换 - 分钟数为 2 位数，必要时带前导零。 |
| TP |  | 约会和日期 time conversion-locale-specific am / pm（小写）。 |
| Tm 值 |  | 约会和;时间转换 - 2 个数字的月份，必要时带前导零。 |
| tD 型 |  | 约会和日期时间转换日期为％tm％td％ty |
|  | 08 | 宽度为八个字符，必要时带前导零。 |
|  | + | 包括标志，无论是正面还是负面。 |
|  | ， | 包括特定于语言环境的分组字符。 |
|  | - | 左对齐.. |
|  | 0.3 | 小数点后三位。 |
|  | 10.3 | 宽度为十个字符，右对齐，小数点后三位。 |

以下程序显示了您可以使用`format`执行的一些格式化。输出显示在嵌入注释中的双引号内：

```
import java.util.Calendar;
import java.util.Locale;

public class TestFormat {

    public static void main(String[] args) {
      long n = 461012;
      System.out.format("%d%n", n);      //  -->  "461012"
      System.out.format("%08d%n", n);    //  -->  "00461012"
      System.out.format("%+8d%n", n);    //  -->  " +461012"
      System.out.format("%,8d%n", n);    // -->  " 461,012"
      System.out.format("%+,8d%n%n", n); //  -->  "+461,012"

      double pi = Math.PI;

      System.out.format("%f%n", pi);       // -->  "3.141593"
      System.out.format("%.3f%n", pi);     // -->  "3.142"
      System.out.format("%10.3f%n", pi);   // -->  "     3.142"
      System.out.format("%-10.3f%n", pi);  // -->  "3.142"
      System.out.format(Locale.FRANCE,
                        "%-10.4f%n%n", pi); // -->  "3,1416"

      Calendar c = Calendar.getInstance();
      System.out.format("%tB %te, %tY%n", c, c, c); // -->  "May 29, 2006"

      System.out.format("%tl:%tM %tp%n", c, c, c);  // -->  "2:34 am"

      System.out.format("%tD%n", c);    // -->  "05/29/06"
    }
}

```

* * *

**Note:**  The discussion in this section covers just the basics of the `format` and `printf` methods. Further detail can be found in the [`Basic I/O`](../../essential/io/formatting.html) section of the Essential trail, in the "Formatting" page.
Using `String.format` to create strings is covered in [Strings](strings.html).

* * *

## DecimalFormat 类

您可以使用 [`java.text.DecimalFormat`](https://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html) 类来控制前导和尾随零，前缀和后缀，分组（千）分隔符和小数分隔符的显示。 `DecimalFormat`在数字格式化方面提供了极大的灵活性，但它可以使您的代码更复杂。

下面的示例通过将模式字符串传递给`DecimalFormat`构造函数来创建`DecimalFormat`对象`myFormatter`。 `DecimalFormat`继承自`NumberFormat`的`format()`方法随后被`myFormatter`调用 - 它接受`double`值作为参数并返回字符串中的格式化数字：

这是一个示例程序，说明`DecimalFormat`的使用：

```
import java.text.*;

public class DecimalFormatDemo {

   static public void customFormat(String pattern, double value ) {
      DecimalFormat myFormatter = new DecimalFormat(pattern);
      String output = myFormatter.format(value);
      System.out.println(value + "  " + pattern + "  " + output);
   }

   static public void main(String[] args) {

      customFormat("###,###.###", 123456.789);
      customFormat("###.##", 123456.789);
      customFormat("000000.000", 123.78);
      customFormat("$###,###.###", 12345.67);  
   }
}

```

输出是：

```
123456.789  ###,###.###  123,456.789
123456.789  ###.##  123456.79
123.78  000000.000  000123.780
12345.67  $###,###.###  $12,345.67

```

下表说明了每行输出。

<caption style="font-weight: bold">`DecimalFormat.java` Output</caption>
| 值 | 图案 | 产量 | 说明 |
| --- | --- | --- | --- |
| 123456.789 | ###，###。### | 123,456.789 | 井号（＃）表示一个数字，逗号是分组分隔符的占位符，句点是小数分隔符的占位符。 |
| 123456.789 | ###。## | 123456.79 | `value`在小数点右边有三位数字，但`pattern`只有两位数。 `format`方法通过四舍五入来处理这个问题。 |
| 123.78 | 000000.000 | 000123.780 | `pattern`指定前导零和尾随零，因为使用 0 字符而不是井号（＃）。 |
| 12345.67 | $ ###，###。### | $ 12,345.67 | `pattern`中的第一个字符是美元符号（$）。请注意，它紧接在格式化的`output`中最左边的数字之前。 |