Math round, floor, ceil и trunc в JavaScript: руководство по округлению чисел в JS
Подробно о методах округления в JavaScript: в меньшую и большую сторону, до целого, до сотых.


Иллюстрация: Polina Vari для Skillbox Media
Округление чисел — одна из базовых операций в программировании. Казалось бы, округлить число несложно. Но на практике возникает много вопросов: какой метод использовать, как работают отрицательные числа, как избежать ошибок при округлении до нужного знака после запятой.
Содержание
- Особенности чисел в JavaScript
- Что такое объект Math в JavaScript
- Math.floor() — округление вниз
- Math.ceil() — округление вверх
- Math.round() — округление по правилам математики
- Math.trunc() — отбрасывание дробной части
- Аргументы какого типа можно использовать в функциях округления
- Как округлить число до заданного количества знаков после запятой
- Примеры задач, в которых используются методы округления
- Типичные ошибки при округлении
В JavaScript для округления используется объект Math, в частности его методы Math.floor, Math.ceil, Math.round и Math.trunc.
Кроме этих, объект Math содержит и другие полезные методы, которые часто используются вместе с округлением: Math.abs(x) возвращает модуль числа, Math.random() — случайное число от 0 до 1, Math.pow(x, y) возводит число x в степень y, Math.sqrt(x) возвращает квадратный корень из числа. О них и о других методах вы можете почитать в документации.
В этой статье мы разберём, как устроено округление в JavaScript, какие в нём есть тонкости и как применять эти знания на практике.
Но сначала немного поговорим о числах в JavaScript.
Особенности чисел в JavaScript
В JavaScript есть два типа чисел. Основной тип — это обычные целые и дробные числа. Они работают в диапазоне примерно от −9 квадриллионов до 9 квадриллионов (точнее — от −(2⁵³ − 1) до 2⁵³ − 1. Такие числа имеют тип number.
let a = 5; // Это number
let b = 3.14; // Тоже number
let c = -100; // И это number
JavaScript использует для хранения таких чисел стандарт, который называется «числа с плавающей точкой двойной точности». Основной смысл в том, что числа хранятся в двоичной системе. Всё в порядке, пока речь идёт о целых числах, но некоторые десятичные дроби невозможно точно записать в двоичном виде — как в десятичной системе невозможно точно записать 1/3 (она превращается в 0,333...).
Поэтому иногда при операциях возникают странности:
0.1 + 0.2 // Результат: 0.30000000000000004
Это не ошибка в JavaScript — так работает хранение чисел в любом языке программирования, который использует этот формат. Чтобы избежать ошибок, приходится округлять результат:
Math.round((0.1 + 0.2) * 100) / 100 // 0.3
Сначала умножаем сумму на 100, чтобы избавиться от запятой, потом округляем и делим обратно.
Второй тип чисел встречается очень редко — это очень большие или очень маленькие числа, выходящие за пределы диапазона обычных чисел (больше чем 2⁵³ − 1 или меньше чем −(2⁵³ − 1)). Этот формат называется BigInt. Такие числа не могут быть дробными, только целыми. Выглядит он вот так:
let big = 1234567890123456789012345678901234567890n;
Обратите внимание: в конце числа стоит буква n. Так JavaScript понимает, что это число типа BigInt.
На практике BigInt нужен редко — в основном он применяется в криптографии. В этой статье мы на нём останавливаться не будем, а поговорим об округлении.
Что такое объект Math в JavaScript
Math — это встроенный объект, который помогает работать с числами. Он умеет округлять числа, находить корень, получать случайные значения и многое другое.
В отличие от других объектов в JavaScript, нельзя использовать Math как функцию или создавать из него копии. Например, вы не можете написать new Math() — это вызовет ошибку.
С объектом Math можно работать только с помощью его свойств и методов — то есть уже готовых команд. Вот как это выглядит:
Math.round(1.7); // Округляет до ближайшего целого: 2
Math.random(); // Возвращает случайное число от 0 до 1, например 0.42
Math.PI; // Возвращает число π (пи): 3.141592653589793
В этой статье мы говорим только об умении Math округлять числа.
Math.floor() — округление вниз
Метод Math.floor() округляет число вниз — до ближайшего целого меньшего или равного значению. Он просто отбрасывает дробную часть и не прибавляет единицу, даже если число близко к следующему целому.
Math.floor(4.9); // 4
Math.floor(4.1); // 4
Если число отрицательное, Math.floor() всё равно округляет вниз — то есть к меньшему числу:
Math.floor(-4.1); // -5
Math.floor(-4.9); // -5
Этот метод используют при расчёте количества страниц или порций — когда дробные части недопустимы.
Допустим, у вас 23 комментария, и на одной странице помещается 5. Сколько полных страниц вы можете отобразить?
let comments = 23;
let perPage = 5;
let pages = Math.floor(comments / perPage); // 4
Ответ — 4 страницы. На пятой осталось бы только 3 комментария, а метод Math.floor() вернёт именно количество полностью заполненных страниц.
Math.ceil() — округление вверх
Округляет аргумент в сторону увеличения до ближайшего целого:
Math.ceil(4.1); // 5
Math.ceil(-4.1); // -4
Отрицательное число тоже округляется к большему значению — в сторону нуля.
У вас 103 записи, и вы хотите выводить по 20 на страницу. Сколько страниц нужно, чтобы вместить всё.
let totalItems = 103;
let perPage = 20;
let totalPages = Math.ceil(totalItems / perPage); // 6
Для размещения 103 записей понадобится 6 страниц.
Math.round() — округление по правилам математики
Метод Math.round() округляет число по привычным школьным правилам:
- Если дробная часть меньше 0,5, округляется в меньшую сторону.
- Если 0,5 и больше — округляется в большую сторону.
Math.round(4.4); // 4
Math.round(4.5); // 5
Math.round(-4.5); // -4
Math.round(-4.6); // -5
При положительных числах всё довольно ожидаемо. А при отрицательных Math.round() округляет в сторону нуля, если дробная часть равна 0,5.
Допустим, видео длится 95 секунд. Посчитаем, сколько это в минутах:
let seconds = 95;
let minutes = Math.round(seconds / 60); // 2
Результат — 2 минуты. Метод округлил 1,58 до ближайшего целого. Если бы видео длилось 89 секунд, получилась бы минута.
Math.trunc() — отбрасывание дробной части
Метод Math.trunc() не округляет число, а просто убирает всё, что стоит после запятой. Он оставляет только целую часть — независимо от того, положительное число или отрицательное.
Math.trunc(4.9); // 4
Math.trunc(-4.9); // -4
Пример 1: координаты
Пользователь мышкой рисует прямоугольник, координаты получаются дробными, но при отрисовке прямоугольника нужны целые числа.
let x = 99.999;
let y = 200.47;
ctx.fillRect(Math.trunc(x), Math.trunc(y), 10, 10);
// Прямоугольник рисуется в точке (99, 200)
Мы используем Math.trunc(), потому что в нашей программе координаты округляются только вниз.
Пример 2: логирование данных
Допустим, программа вычисляет скидку −12,95. Для журнала аудита нужно сохранить только целую часть — без копеек.
let discount = -12.95;
let intPart = Math.trunc(discount); // -12
Так мы избавляемся от дробной части без округления и сохраняем грубое значение.
Аргументы какого типа можно использовать в функциях округления
Методы Math.round(), Math.floor(), Math.ceil() и Math.trunc() обычно работают с числами. Но JavaScript устроен гибко — если вы случайно (или специально) передаёте в них значение другого типа, движок попытается превратить его в число. Иногда это работает, иногда — нет. Если Math не сможет привести аргумент к числу, он возвращает NaN.
NaN (сокращение от Not-a-Number) — это специальное значение в JavaScript, которое означает «не число». Оно появляется, когда операция с числами не может дать корректный результат, например:
0 / 0 // NaN — деление ноля на ноль
Math.sqrt(-1) // NaN — нельзя извлечь корень из отрицательного числа
parseInt("abc") // NaN — строка не может быть преобразована в число
Давайте посмотрим, как ведут себя разные типы значений.
Строки
console.log(Math.ceil("abc")); // NaN
console.log(Math.round("11.15")); // 11
Если в строке текст, результат будет NaN. Строку с числом JavaScript сначала приводит к числу, а затем округляет.
Булевы значения (true, false)
console.log(Math.ceil(true)); // 1
console.log(Math.round(false)); // 0
Булевы значения true и false преобразуются в числа 1 и 0 соответственно.
Значения null, undefined, Nan
Значение null в JavaScript означает «пусто». Его можно задать вручную, если переменная пока ничего не хранит.
let value = null;
console.log(Math.ceil(value)); // 0
При округлении null логично превращается в 0.
Значение undefined означает, что переменная есть, но в ней ничего не лежит. Это значение присваивается автоматически, если вы что-то объявили, но не задали.
let value;
console.log(Math.round(value)); // NaN
Здесь переменная value существует, но округлить её невозможно. Результат — NaN.
Если вы попытаетесь округлить NaN, результат снова будет NaN:
console.log(Math.ceil(NaN)); // NaN
Что будет, если округлять массив
В JavaScript даже массив можно округлить. Звучит странно, но иногда это работает.
Рассмотрим три примера:
console.log(Math.ceil([5.3])); // 6
console.log(Math.round([])); // 0
console.log(Math.ceil([1, 5])); // NaN
Массив [5.3] сначала превращается в обычное число 5.3. После этого Math.ceil() округляет его вверх, получается 6.
Пустой массив [] превращается в 0. Поэтому результат округления — ноль.
В последнем массиве два значения: [1, 5]. JavaScript не может понять, какое число имелось в виду. Поэтому результат — NaN.
Рекомендация
Если вы работаете с вводом от пользователя, всегда явно приводите его к числу перед округлением:
let inputValue = prompt("Введите число:");
Math.floor(Number(inputValue));
Это поможет избежать непредсказуемого поведения. NaN опасен, потому что он распространяется по цепочке вычислений:
let x = NaN;
let y = x + 5; // Тоже NaN
Как округлить число до заданного количества знаков после запятой
Методы Math напрямую не поддерживают округление до знаков после запятой. Чтобы округлить число, например, до 2 знаков, есть несколько способов, в том числе с использованием альтернативных методов.
Округление вручную
Чтобы округлить число до n знаков после запятой:
- умножим его на 10^n — чтобы сдвинуть запятую;
- применим округление;
- результат разделим обратно на 10^n.
Например, округлим число 1,23789 до 2 знаков после запятой:
function roundTo(num, decimals) {
const factor = 10 ** decimals;
return Math.round(num * factor) / factor;
} // Функция округляет число до n знаков после запятой
roundTo(1.23789, 2); // 1.24
roundTo(1.234, 1); // 1.2
Альтернативный метод toFixed(digits)
Метод toFixed() округляет число до нужного количества знаков после запятой. Он работает по обычным правилам математики: если следующая цифра 5 и больше — округляем вверх. Но этот метод возвращает строку, а не число.
const num = 5.6789;
const result = num.toFixed(2);
console.log(result); // "5.68"
Здесь число округлилось до двух знаков после запятой. Получилась строка "5.68".
Если указать 0 или вообще ничего не указывать, округление произойдёт до целого числа:
console.log(num.toFixed(0)); // "6"
console.log(num.toFixed()); // "6"
Строку можно преобразовать обратно в число с помощью parseFloat():
const number = parseFloat(result);
console.log(number); // 5.68
Примеры задач, в которых используются методы округления
Методы Math.round, Math.floor, Math.ceil, Math.trunc часто применяются на практике.
В расчётах (финансы, средние значения, скидки):
Представьте, что у вас в корзине товар на сумму 349,999 рубля.На товар действует скидка 12,75 рубля, но магазин округляет скидку вниз до целого числа (чтобы не переплатить). После применения скидки финальная сумма должна быть округлена до ближайшего рубля.
Шаги:
- Округлить скидку вниз (Math.floor).
- Вычесть скидку из суммы.
- Округлить финальную сумму до ближайшего целого (Math.round).
// Исходная сумма товаров
let total = 349.999;
// Скидка, рассчитанная системой
let discount = 12.75;
// Округляем скидку вниз, чтобы не потерять деньги
let discountApplied = Math.floor(discount); // 12
// Промежуточная сумма после скидки
let subtotal = total - discountApplied; // 337.999
// Округляем итоговую сумму до ближайшего рубля
let finalTotal = Math.round(subtotal); // 338
// Выводим результат
console.log(`Итоговая сумма к оплате: ${finalTotal} руб.`);
// Результат: "Итоговая сумма к оплате: 338 руб."
UI и frontend (разметка, размеры, шрифты)
Представьте, что вы создаёте вёрстку сетки с тремя колонками и хотите, чтобы:
- Колонки целиком поместились в контейнер.
- Центральный элемент был идеально выровнен по горизонтали.
Расчёт ширины колонки:
let containerWidth = 799.8; // Ширина всего контейнера (например, в px)
let columnCount = 3; // Количество колонок
let columnWidth = Math.floor(containerWidth / columnCount); // 266 px
console.log(`Ширина одной колонки: ${columnWidth}px`);
// Ширина одной колонки: 266 px
Объяснение:
- Находим ширину одной колонки:
799.8 / 3 = 266.6.
- Округляем вниз, чтобы все три колонки точно поместились в контейнер:
Math.floor(266.6) = 266.
- Проверим ответ:
266 × 3 = 798 (всё помещается).
1,8 пикселя остаются — их можно использовать как отступы между колонками.
Центрирование элемента по горизонтали
У нас есть родительский блок шириной 800 px и вложенный элемент шириной 375 px. Нужно найти и выровнять центральный элемент по горизонтали.
Решение:
let parentWidth = 800; // Ширина родительского блока
let childWidth = 375; // Ширина вложенного элемента
let left = Math.round((parentWidth - childWidth) / 2); // 213 px
console.log(`Левый отступ для центрирования: ${left}px`);
Объяснение:
- Найдём левый отступ центрального элемента внутри родительского блока:
(800 − 375) / 2 = 212.5.
- Округляем полученное значение до ближайшего целого пикселя, чтобы избежать «размытых» краёв или смещения.
Math.round(212.5) = 213 px.
Работа с координатами
Вы хотите плавно перемещать элемент (например, кружок) слева направо. Координата x вычисляется при каждом кадре — она может быть дробной, но CSS left принимает целое число пикселей. Если задать дробное значение, браузер может отрисовать элемент размыто или вызвать дрожание.
Решение:
let x = 123.78; // Текущая позиция из расчёта
// Округляем координату до ближайшего целого
element.style.left = Math.round(x) + "px"; // "124px"
Объяснение:
- x = 123.78 — позиция рассчитывается динамически — например, по времени или скорости.
- Округляем до целого: Math.round(x) = 124.
- CSS требует чётких координат, поэтому element.style.left = 124px.
Если оставить дробные координаты (123.78px), элемент может отрисовываться размыто или дрожать при движении.
Типичные ошибки при округлении
Рассмотрим ошибки, которые часто совершают при использовании методов Math.
Неправильное использование Math.round()
Иногда новички пытаются использовать Math.round() с двумя аргументами.
Math.round(1.2345, 2) // 1
Это не работает — Math.round принимает только одно число. Второй аргумент игнорируется.
Решение: использовать один аргумент.
Math.round(1.2345 * 100) / 100 // 1.23
Ожидание точности при работе с дробями
Иногда новички думают, что округление решит проблему плавающей запятой:
// Неправильное ожидание:
Math.round(0.1 + 0.2) === 0.3; // false (0.30000000000000004 округляется до 0)
Решение: нужно сначала корректировать точность.
const sum = 0.1 + 0.2;
Math.round(sum * 10) / 10 === 0.3; // true
Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!