Объект Math
Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.
Math — не класс и не функция, а объект-склад: полка с готовыми формулами. Ничего не нужно создавать через new, всё вызывается прямо у него: Math.round(4.7), Math.max(1, 9).
Из дробного числа почти всегда нужно получить целое: страниц в списке, пикселей, товаров на складе. За это отвечают четыре метода, и отличаются они только направлением, в которое «уезжает» число.
На положительных числах floor и trunc дают одно и то же, поэтому разницу между ними легко не заметить — до первого минуса. О нём следующий раздел.
Отдельного метода нет, но есть приём: умножить, округлить, поделить обратно. Он не всесилен, и причина та же, что у toFixed: почему записанное в коде 1.005 хранится чуть меньше, чем выглядит, разбирает статья «Числа: точность и округление». Здесь важно следствие: «пограничное» число уезжает не туда.
floor и ceil двигают число по числовой прямой: первый — влево, второй — вправо. trunc двигает его к нулю, то есть для отрицательных чисел — вправо. Поэтому Math.floor(-1.2) даёт −2, а Math.trunc(-1.2) даёт −1.
У round своя странность: «ровно половина» округляется вверх, а не «от нуля». Из-за этого −1.5 становится −1, хотя 1.5 становится 2.
| Число | round | floor | ceil | trunc |
|---|---|---|---|---|
| 1.5 | 2 | 1 | 2 | 1 |
| -1.4 | -1 | -2 | -1 | -1 |
| -1.5 | -1 | -2 | -1 | -1 |
| -1.6 | -2 | -2 | -1 | -1 |
floor — «ниже по прямой», trunc — «отрезать хвост». Для 1.2 это одно и то же, для -1.2 — уже нет.
Math.random() возвращает дробное число от 0 включительно до 1 не включительно. Аргументов у него нет, диапазон не настраивается — всё остальное вы считаете сами.
Чтобы получить целое от min до max включительно, растягиваем отрезок на нужную длину и отсекаем дробь через floor. Ширина диапазона — max - min + 1: единица добавлена ровно затем, чтобы верхняя граница тоже могла выпасть.
С round диапазон вроде бы тот же, но крайние значения выпадают вдвое реже: к ним ведёт половинка отрезка, а к серединным — целый отрезок. Проверим на трёх числах.
Оба метода принимают сколько угодно аргументов — но именно аргументов, а не массив. Массив разворачивают спредом ....
Последняя строка — не шутка, а ловушка: без аргументов Math.max возвращает -Infinity, а Math.min — Infinity. Значит, пустой массив в спреде тихо превратится в бесконечность. И любой NaN среди аргументов делает результат NaN целиком.
Самая частая пара — «зажать значение в границах»: наружный min держит потолок, внутренний max — пол.
Math.pow(a, b) возводит a в степень b, и у него есть более короткий синоним — оператор **. Math.sqrt берёт квадратный корень, Math.abs снимает знак.
Степень не обязана быть целой и положительной: дробная даёт корень, отрицательная — деление. Для кубического корня есть отдельный Math.cbrt, он точнее.
Math.hypot считает корень из суммы квадратов всех аргументов — ту самую гипотенузу из школы. Это готовая формула расстояния: разница по X, разница по Y, и вот вам длина отрезка.
Ручной вариант короче не становится, зато ломается на больших числах: квадрат может не поместиться в число и стать бесконечностью. Math.hypot внутри масштабирует значения и такой аварии избегает.
- Math — обычный объект с готовыми функциями: без new, всё вызывается как Math.что-то().
- floor и ceil двигают число по числовой прямой, trunc — к нулю; на отрицательных floor и trunc расходятся, а round при ровной половине идёт вверх (-1.5 даёт -1).
- Math.random() возвращает дробь от 0 до 1 не включительно; целое в диапазоне — Math.floor(Math.random() * (max - min + 1)) + min.
- Math.min и Math.max берут аргументы, а не массив: разворачивайте спредом и помните про -Infinity у пустого вызова.
- pow (или **), sqrt, abs решают школьную арифметику, а Math.hypot(a, b) сразу даёт расстояние и не переполняется на больших числах.
1/3Что выведет Math.floor(-1.5)?
2/3Чему равен Math.max() без единого аргумента?
3/3Какое выражение даёт случайное целое от 1 до 6 включительно, причём все шесть значений равновероятны?
Случайное целое в диапазоне
Напишите функцию randomInt(min, max), которая возвращает случайное целое число от min до max включительно — обе границы должны иногда выпадать.
Ширина диапазона — max - min + 1: единица нужна, чтобы верхняя граница тоже попадала в выборку. Растягиваем Math.random() на эту ширину, срезаем дробь через Math.floor и сдвигаем на min.
Именно floor, а не round: с округлением к ближайшему крайние значения выпадали бы вдвое реже остальных.
Самое далёкое от нуля
Дан массив чисел. Верните тот элемент, который дальше всех от нуля, — со своим знаком. Для [3, -12, 7, -5] ответ -12.
Расстояние до нуля — это модуль. Считаем максимальный модуль по всему массиву, а потом ищем первый элемент с таким модулем, чтобы вернуть его вместе со знаком.
Math.max не принимает массив, поэтому нужен спред. Передавать Math.abs прямо в map безопасно: лишние аргументы (индекс и массив) он просто игнорирует.