JavaRush /Курсы /JAVA 25 SELF /Округление и форматирование чисел

Округление и форматирование чисел

JAVA 25 SELF
6 уровень , 4 лекция
Открыта

1. Введение

В реальной жизни редко бывает, чтобы нам нужно было видеть длинные «хвосты» после запятой. Например, если вы считаете стоимость товара, зарплату, средний балл или площадь комнаты, — вам обычно достаточно пары знаков после запятой, а не 15-ти.

Например, результат деления:

double x = 10.0 / 3.0;
System.out.println(x); // 3.3333333333333335

Пользователь, увидев такой результат, может испугаться и подумать, что программа сошла с ума. Поэтому числа часто нужно округлять — до ближайшего целого, до двух знаков после запятой и так далее.

В Java для этого есть несколько удобных инструментов.

2. Метод Math.round(): округление до ближайшего целого

Самый простой способ округлить число — воспользоваться методом Math.round(). Он принимает число с плавающей точкой (можно и float, и double) и возвращает ближайшее целое.

Как работает Math.round

  • Если дробная часть меньше 0.5 — округляет вниз.
  • Если дробная часть 0.5 или больше — округляет вверх.

Примеры:

System.out.println(Math.round(2.3)); // 2
System.out.println(Math.round(2.7)); // 3
System.out.println(Math.round(2.5)); // 3
System.out.println(Math.round(-2.5)); // -2

Тип возвращаемого значения

  • Если передать float, вернётся int.
  • Если передать double, вернётся long.
float f = 5.8f;
int roundedF = Math.round(f); // 6

double d = 5.8;
long roundedD = Math.round(d); // 6

Обратите внимание: иногда это вызывает удивление — округлили double, а получили long! Если вам нужен int, придётся сделать явное приведение:

int rounded = (int) Math.round(5.6); // 6

3. Округление до нужного количества знаков после запятой

Часто нужно округлить не до целого, а, например, до двух знаков после запятой (для денег, процентов и т.д.).

В Java нет «волшебного» метода вроде Math.roundTo2Digits(), но можно сделать это вручную.

Способ 1: математический трюк с умножением и делением

  1. Умножаем число на 100 (если нужно два знака).
  2. Округляем до целого с помощью Math.round.
  3. Делим обратно на 100.

Пример:

double value = 3.14159;
double rounded = Math.round(value * 100.0) / 100.0;
System.out.println(rounded); // 3.14

Как это работает:

  • 3.14159 * 100 = 314.159
  • Math.round(314.159) = 314
  • 314 / 100.0 = 3.14

4. Форматирование чисел: класс DecimalFormat

Иногда нужно не только округлить число, но и вывести его красиво — с определённым количеством знаков после запятой, ведущими нулями, разделителями разрядов и т.п. Для этого в Java есть класс DecimalFormat из пакета java.text.

Как работает DecimalFormat

  1. Создаём объект с нужным шаблоном.
  2. Вызываем у него метод format(...).
import java.text.DecimalFormat;

double value = 3.14159;

DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value)); // 3.14

Как устроен шаблон

  • "0.00" — всегда два знака после запятой (даже если число целое).
  • "0.###" — до трёх знаков после запятой, лишние нули не выводятся.
  • "#,##0.00" — добавляет разделители тысяч (например, "1,234.56").

Примеры разных шаблонов:

Шаблон Число Результат
"0.00"
2 2.00
"0.00"
2.5 2.50
"0.00"
2.567 2.57
"0.###"
2.567 2.567
"0.###"
2.5 2.5
"#,##0.00"
12345.678 12,345.68

Пример с разделителями тысяч

DecimalFormat df = new DecimalFormat("#,##0.00");
System.out.println(df.format(1234567.89)); // 1,234,567.89

Пример: вывод без лишних нулей

DecimalFormat df = new DecimalFormat("0.##");
System.out.println(df.format(3.1));   // 3.1
System.out.println(df.format(3.141)); // 3.14
System.out.println(df.format(3.145)); // 3.15

5. Форматирование с помощью String.format

Иногда для простых случаев удобно использовать String.format — встроенный способ форматировать строки, похожий на printf в других языках.

double value = 3.14159;
System.out.println(String.format("%.2f", value)); // 3.14

Здесь "%.2f" — означает «вывести число с двумя знаками после запятой».

Сравнение подходов:

  • DecimalFormat — мощнее, поддерживает шаблоны и локализацию, удобен для разделителей тысяч.
  • String.format — проще, если нужно просто задать количество знаков после запятой.

6. Особенности округления: Math.floor, Math.ceil, Math.rint

  • Math.floor(x) — округляет вниз (в меньшую сторону), в том числе для отрицательных чисел.
  • Math.ceil(x) — округляет вверх (в большую сторону).
  • Math.rint(x) — округляет до ближайшего целого, но возвращает double.

Примеры:

System.out.println(Math.floor(2.7)); // 2.0
System.out.println(Math.ceil(2.1));  // 3.0
System.out.println(Math.rint(2.5));  // 2.0 (да-да, не опечатка!)
System.out.println(Math.rint(3.5));  // 4.0

Внимание: Math.rint иногда округляет «к ближайшему чётному» — это правило (т.н. banker's rounding) помогает уменьшать накопление ошибок при массовых вычислениях.

7. Полезные нюансы

Визуализация: таблица округлений

Число Math.round Math.floor Math.ceil Math.rint
2.3 2 2.0 3.0 2.0
2.5 3 2.0 3.0 2.0
3.5 4 3.0 4.0 4.0
-2.3 -2 -3.0 -2.0 -2.0
-2.5 -2 -3.0 -2.0 -2.0

Округление — это не форматирование!

Очень важно понимать разницу между округлением и форматированием.

  • Округление — изменение значения числа (например, 2.7182.72).
  • Форматирование — изменение того, как число выглядит при выводе (например, 2.718"2.72" на экране, но в памяти остаётся 2.718).
double x = 2.718;
System.out.println(String.format("%.2f", x)); // 2.72
System.out.println(x); // 2.718

Если вы хотите использовать округлённое число в дальнейших вычислениях — округляйте математически! Если только для вывода — форматируйте.

8. Типичные ошибки при округлении и форматировании чисел

Ошибка №1: Округлили только для вывода, а дальше используем «хвостатое» число.
Очень частая ситуация — вывести красиво отформатированное значение на экран, а затем использовать исходное «длинное» число в расчётах. Для денег, баллов и итогов — сначала округлите (например, Math.round или приём с умножением/делением), затем сохраняйте/передавайте пользователю.

Ошибка №2: Ожидание, что Math.round(x) вернёт double с двумя знаками после запятой.
Math.round() всегда округляет до ближайшего целого: для float возвращает int, для doublelong. Для двух знаков используйте умножение/деление или форматирование.

Ошибка №3: Использование DecimalFormat для вычислений.
DecimalFormat.format() возвращает строку. Использовать её в арифметике нельзя: получите ошибку компиляции или NumberFormatException при обратном разборе.

Ошибка №4: Неправильный шаблон DecimalFormat.
Шаблон должен соответствовать ожиданиям: "0.00" всегда покажет два знака ("2.00"), а "0.##" уберёт лишние нули ("2", "2.1", "2.12").

Ошибка №5: Потеря точности при делении на 100.
Если вы делите int на int, результат тоже int!

int a = 5;
System.out.println(a / 2); // 2, а не 2.5!

Чтобы деление было «дробным», хотя бы один операнд должен быть double:

int a = 5;
System.out.println(a / 2.0); // 2.5
1
Задача
JAVA 25 SELF, 6 уровень, 4 лекция
Недоступна
Оценка ресурсов для космической колонии 🛰️
Оценка ресурсов для космической колонии 🛰️
1
Задача
JAVA 25 SELF, 6 уровень, 4 лекция
Недоступна
Точный расчёт стоимости эликсира с налогом 💰
Точный расчёт стоимости эликсира с налогом 💰
1
Задача
JAVA 25 SELF, 6 уровень, 4 лекция
Недоступна
Красивое представление отчёта о доходах 📊
Красивое представление отчёта о доходах 📊
1
Задача
JAVA 25 SELF, 6 уровень, 4 лекция
Недоступна
Отображение мировых продаж в удобном формате 🌍
Отображение мировых продаж в удобном формате 🌍
Комментарии (13)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Overbyaka Уровень 8
16 января 2026
Ошибка №5: Потеря точности при делении на 100 Видимо не ту информацию здесь приложили, хотелось бы увидеть пример ошибки..
Kismet Уровень 15
24 ноября 2025
"Создайте переменную типа double и присвойте ей значение, например, 12345678.9012 (миллионов)" В условии написано "например", но когда я ввожу любое значение не равняющийся на этот пример, то мне выдает ошибку, но при этом в требовании указано, что переменная должна равняться на какое-либо значение. Почему так?
Rust =)) Уровень 7
4 января 2026
некоторые рекомендации здесь носят обязательный характер. это нормально :)
Kidze Уровень 21
9 октября 2025
Если кого то смущает в последней задаче, что разделители не запятая, а пробел, то это зависит от нашей локали, надо вручную прописывать нужную если хотите поменять их. Пишем:

DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
DecimalFormat df = new DecimalFormat("#,###.00", symbols);
Я так понял если пользователь из другой страны запустит ваш код, то у него будет отображаться формат его локали, если мы не прописывали ее, а дефолтную используем.(т.е. наши пробелы превратятся у него в запятые) Я так понял, лучше конечно самим почитать=)
Vlad Privalov Уровень 11
7 октября 2025
Последняя задача не компилируется при этом решение верное
Kidze Уровень 21
9 октября 2025
Отписал в своем комменте почему, если интересно.
Vlad Privalov Уровень 11
9 октября 2025
Спасибо
Garik Уровень 11
15 октября 2025
Попробуй использовать полный формат, вместо DecimalFormat > java.text.DecimalFormat
Сергей Морозов Уровень 14
27 октября 2025
импорта DecimalFormat нет. Вместо импорта можно java.text.DecimalFormat
Александр Уровень 50
1 октября 2025
Проверил, Math.round(-2.5) действительно возвращает -2. При этом по правилам алгебраического округления -2.5 округляется до -3, если не ошибаюсь. У кого какие мысли по этому поводу?
TaReN Уровень 11
7 октября 2025
Оно округляет в большую сторону... -2 > -3 поскольку оно ближе к пложительному(+му) значению
Александр Уровень 50
8 октября 2025
Есть сомнения, ведь по этой логике минус 2.6 тоже должно округляться до большего числа, то есть до -2 (минус 2 больше чем минус 3). Однако, это не так. И в теории, и в практике Math.round(-2.6) дает результат -3. Вот, посмотрел правило арифметического округления. Всё, оказывается, просто Если N+1 знак <5, то №-ый знак не меняется, а N+1 и все последующие отбрасываются. Если N+1 знак >=5, то №-ый знак увеличивается на единицу, а все знаки начиная с N+1 обнуляются. То есть, на положительность/отрицательность числа внимания вообще обращать не нужно: 2.4 (4 < 5, поэтому 2 не меняется, 4 отбрасывается) округляется до 2 2.5 (5 = 5, поэтому 5 отбрасывается, а 2 увеличивается на 1) до 3 -2.4 (4 < 5, поэтому 2 не меняется, 4 отбрасывается) до -2 -2.5 (5 = 5, поэтому 5 отбрасывается, а 2 увеличивается на 1) до -3 В последующих лекциях будет глава "форматирование" с округлением. Специально проверял работу метода format(). Вот там результат ожидаемый: -2.5 округляется до -3. ПС: для себя вопрос не закрываю.
Илья Уровень 7
29 декабря 2025
Вот ответ от нейросети: Метод Math.round() в Java работает по принципу "округления к ближайшему целому, а при равном расстоянии (когда дробная часть равна 0.5) — в сторону положительной бесконечности".