Как форматировать числа в Java
Форматирование чисел в Java с помощью String.format, printf, DecimalFormat и NumberFormat.
Java предоставляет несколько способов превратить сырой int, double или BigDecimal в удобную для человека строку: разделители тысяч, фиксированное количество десятичных знаков, символы валюты и проценты. В этой главе рассматриваются наиболее часто используемые инструменты: String.format/printf, DecimalFormat и NumberFormat с поддержкой локали. Информацию об используемых числовых типах см. в разделе Java Numbers; полный список преобразований printf см. в разделе Java String Formatting.
Быстрое форматирование с String.format и printf
Для разового форматирования в строке лога или System.out форматная строка — самый лаконичный подход. printf выводит значение напрямую; String.format возвращает строку, которую можно сохранить.
double price = 1234.5;
System.out.printf("%.2f%n", price); // 1234.50
String s = String.format("%,.2f", price); // 1,234.50
System.out.println(String.format("%08.2f", 42.5)); // 00042.50Спецификатор %.2f фиксирует два знака после запятой, флаг , добавляет разделители групп разрядов, а %08.2f дополняет поле нулями до ширины 8. Используйте %n вместо \n для корректного разрыва строки на любой платформе. Разделитель групп зависит от локали по умолчанию, поэтому тот же код может выводить 1.234,50 на машине с немецкой локалью.
Пользовательские шаблоны с DecimalFormat
Когда нужен полный контроль над шаблоном или требуется форматировать множество значений одним переиспользуемым объектом, используйте DecimalFormat. Вывод описывается шаблоном из символов # (необязательная цифра) и 0 (обязательная цифра).
DecimalFormat df = new DecimalFormat("#,##0.00");
df.format(1234.5); // "1,234.50"
df.format(0.5); // "0.50"
DecimalFormat sci = new DecimalFormat("0.###E0");
sci.format(123456); // "1.235E5"По умолчанию DecimalFormat использует режим округления RoundingMode.HALF_EVEN, что может удивить (2.5 округляется до 2). Установите df.setRoundingMode(RoundingMode.HALF_UP), если вам нужно привычное «округление половины вверх». Один экземпляр DecimalFormat не является потокобезопасным, поэтому создавайте по одному на каждый поток или используйте синхронизацию.
Валюта и проценты с учётом локали
Для валюты и процентов не стройте шаблон вручную. Фабричные методы NumberFormat выбирают правильный символ, разделители и количество знаков для заданной Locale.
NumberFormat us = NumberFormat.getCurrencyInstance(Locale.US);
us.format(1234.5); // "$1,234.50"
NumberFormat pct = NumberFormat.getPercentInstance(Locale.US);
pct.format(0.87); // "87%"Обратите внимание: форматтер процентов умножает значение на 100, поэтому передаётся 0.87, чтобы получить 87%. Указание правильной Locale обеспечивает корректный вывод для каждого рынка.
| Подход | Лучше всего для | Учёт локали | Переиспользование |
|---|---|---|---|
printf / String.format | разовый вывод | да (локаль по умолчанию) | нет |
DecimalFormat | пользовательские шаблоны, массовое форматирование | да (настраивается) | да (не потокобезопасен) |
NumberFormat.getCurrencyInstance | деньги | да | да |
NumberFormat.getPercentInstance | доли | да | да |
Полный выполняемый пример
Программа ниже форматирует одно и то же число четырьмя разными способами, а затем демонстрирует дополнение нулями, чтобы можно было сравнить результаты рядом.
Что можно узнать из результата выполнения:
printfс%,.2fвыводит1,234,567.89, добавляя разделители групп и фиксируя два знака после запятой.DecimalFormat("#,##0.00")даёт тот же результат1,234,567.89, но в виде переиспользуемой возвращаемой строки.getCurrencyInstance(Locale.US)добавляет символ$, выдавая$1,234,567.89.getPercentInstanceумножает0.8736на 100 и округляет до87%.%08.2fдополняет42.5нулями до ширины 8, выводя00042.50.