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 лекция
Недоступна
Отображение мировых продаж в удобном формате 🌍
Отображение мировых продаж в удобном формате 🌍
Комментарии (22)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
nightmarakesh Уровень 45
20 июня 2026
По логике в задаче на металл надо округлять всегда в большую сторону, тк металла иначе не хватит. Понятно, что это формальность, но все же раз пишут контекст, по хорошему следовать емую
Ivan Kulazhenkov Уровень 1
16 июня 2026
Немножко про rint: Когда дробная часть числа равна ровно 0.5, Math.rint() не округляет всегда вверх, а выбирает ближайшее ЧЁТНОЕ целое число. Почему это называется «Banker's Rounding» (Округление банкира)? Представь, что ты банк и ежедневно округляешь тысячи процентов или курсов валют. Если использовать школьное округление (всегда вверх на .5): 1.5 → 2 2.5 → 3 3.5 → 4 4.5 → 5 Все числа с .5 округляются вверх. Со временем накапливается систематическая ошибка — все суммы становятся чуть больше реальных. Банк теряет деньги (или зарабатывает, но это уже другая история). Если использовать Banker's Rounding: 1.5 → 2 (чётное) 2.5 → 2 (чётное) 3.5 → 4 (чётное) 4.5 → 4 (чётное) Половина .5 округляется вверх, половина — вниз. Ошибка в среднем стремится к нулю. Это честнее для больших массивов данных.
Gans Electro Уровень 40
26 мая 2026
Не знал про long из round, впервые вижу rint. В SQL можно писать ROUND('15.123', 2) и будет 15.12. Видимо забыл что в Java такого нет
Gans Electro Уровень 40
26 мая 2026
Пока читал лекций задумался о числах, о 0 о 1. Вспомнил статью, подумал о сути вещей и вернулся
Юрий Уровень 11
23 апреля 2026
В четвертой задаче перед классом надо импортировать DeciamlFormat import java.text.DecimalFormat;
19 марта 2026
Как то странновато ;)
Nevidimka Уровень 17
2 апреля 2026
Видимо написал правильно, но не импортировал класс
Михаил Морозов Уровень 5
21 января 2026
Классная тема. Всё подробно и интересно. 👍👍👍 Надеюсь вспомню её через пол года. Но пока это самое прикольное 🙂
Overbyaka Уровень 1
16 января 2026
Ошибка №5: Потеря точности при делении на 100 Видимо не ту информацию здесь приложили, хотелось бы увидеть пример ошибки..
Kismet Уровень 24
24 ноября 2025
"Создайте переменную типа double и присвойте ей значение, например, 12345678.9012 (миллионов)" В условии написано "например", но когда я ввожу любое значение не равняющийся на этот пример, то мне выдает ошибку, но при этом в требовании указано, что переменная должна равняться на какое-либо значение. Почему так?
Rust =)) Уровень 11
4 января 2026
некоторые рекомендации здесь носят обязательный характер. это нормально :)
Kidze Уровень 38
9 октября 2025
Если кого то смущает в последней задаче, что разделители не запятая, а пробел, то это зависит от нашей локали, надо вручную прописывать нужную если хотите поменять их. Пишем:

DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
DecimalFormat df = new DecimalFormat("#,###.00", symbols);
Я так понял если пользователь из другой страны запустит ваш код, то у него будет отображаться формат его локали, если мы не прописывали ее, а дефолтную используем.(т.е. наши пробелы превратятся у него в запятые) Я так понял, лучше конечно самим почитать=)