Набор статических методов
java.lang.Math это класс, полный готовых математических функций: степени, корни, модуль, округление, тригонометрия, логарифмы и случайные числа. Пользоваться им просто по двум причинам:
- Он находится в
java.lang, который каждый файл Java импортирует автоматически. Строкуimportписать не нужно. - Все методы
static. Вы вызываете их через имя класса,Math.sqrt(25), и никогда не создаёте объектMath. Что означаетstatic, объяснено на странице про статические члены.
Обратите внимание: одни результаты печатаются с .0, другие без. У каждого метода Math фиксированный тип результата, и знать его значит знать большую часть того, что нужно знать об этом классе.
| Метод | Что делает | Возвращает |
|---|---|---|
Math.pow(a, b) | a в степени b | double |
Math.sqrt(x) | квадратный корень | double |
Math.cbrt(x) | кубический корень | double |
Math.abs(x) | модуль числа | тот же тип, что у x |
Math.max(a, b) / Math.min(a, b) | большее / меньшее из двух | более широкий из двух типов |
Math.round(x) | ближайшее целое | long для double, int для float |
Math.floor(x) / Math.ceil(x) | округление вниз / вверх | double |
Math.random() | случайное число от 0.0 до 1.0 | double |
Math.PI, Math.E | константы π и e | double |
Math.pow: степени
Math.pow(base, exponent) возводит число в степень. Метод принимает два параметра double и возвращает double, даже если вы передаёте целые числа:
Чтобы сохранить результат в int, приведите его через (int). Для небольших целых степеней результат double точный, и приведение даёт правильный ответ. Проблемы начинаются на больших результатах: double больше Integer.MAX_VALUE (2 147 483 647) приводится ровно к Integer.MAX_VALUE, поэтому (int) Math.pow(2, 40) даёт 2147483647. Для больших степеней приводите к long и помните, что выше 2⁵³ double не может точно представить каждое целое число. Что приведение делает со значением, разобрано на странице про приведение типов.
Оператора возведения в степень в Java нет. 2 ^ 3 компилируется, но ^ это побитовое исключающее ИЛИ, и результат равен 1, а не 8. Это одна из самых частых ошибок новичков в математическом коде на Java.
double от десяти миллионов и больше печатается в экспоненциальной записи, и это удивляет тех, кто впервые печатает степень десяти:
1.0E7 означает 1.0 × 10⁷. Значение то же самое, меняется только вид при печати. Чтобы напечатать его обычными цифрами, приведите к long или отформатируйте через String.format("%.0f", value).
Math.sqrt и Math.cbrt: корни
Math.sqrt(x) возвращает квадратный корень из x как double. Math.cbrt(x) возвращает кубический корень.
Квадратный корень из отрицательного числа не является действительным числом, поэтому Math.sqrt(-4) возвращает NaN («не число»), а не выбрасывает исключение. NaN распространяется через любую арифметику, в которую попадает, поэтому проверяйте входные данные перед извлечением корня, если возможны отрицательные значения. Math.hypot(a, b) вычисляет sqrt(a*a + b*b) напрямую, и это обычный способ найти расстояние между двумя точками.
Math.abs: модуль числа
Math.abs(x) убирает знак. В отличие от pow и sqrt, он возвращает тот же тип, что получил: int для int, double для double.
Обычно его применяют к разности, когда важна величина, а не направление, например к расстоянию между двумя позициями.
Math.max и Math.min
Math.max(a, b) возвращает большее из двух значений, а Math.min(a, b) меньшее. Они принимают ровно два аргумента. Для трёх и более вкладывайте вызовы друг в друга:
Когда у двух аргументов разные типы, более узкий сначала расширяется. Math.max(3, 7.5) сравнивает два значения double и возвращает double. Последний пример зажимает значение в диапазон от 0 до 100: Math.min ограничивает его сверху числом 100, а Math.max не даёт опуститься ниже 0.
Округление: round, floor, ceil
В Java три метода округления, и они различаются и направлением, и типом результата:
Math.roundокругляет до ближайшего целого. Значение ровно посередине округляется вверх, в сторону плюс бесконечности, поэтому2.5становится3, а-2.5становится-2. Для аргументаdoubleон возвращаетlong(а дляfloatвозвращаетint).Math.floorвсегда округляет вниз, в сторону минус бесконечности, и возвращаетdouble.Math.ceilвсегда округляет вверх, в сторону плюс бесконечности, и возвращаетdouble.- Приведение
(int)вообще не округление: оно отбрасывает дробную часть, а это сдвигает положительные числа вниз, а отрицательные вверх.
Поскольку Math.round(double) возвращает long, присваивание его int без приведения не компилируется:
int n = Math.round(2.6); // error: incompatible types: possible lossy conversion from long to int
int m = (int) Math.round(2.6); // OK, m равно 3
long k = Math.round(2.6); // OK
Чтобы округлить до определённого числа знаков после запятой, умножьте, округлите и разделите обратно. Деление на 100.0 (double), а не на 100, сохраняет дробную часть:
Во второй строке long делится на int, а это целочисленное деление, поэтому дробная часть теряется. Когда округлённое число нужно только показать, String.format("%.2f", value) проще и не меняет хранимое значение.
Math.random: случайные числа
Math.random() возвращает double не меньше 0.0 и меньше 1.0. При каждом вызове значение новое, поэтому вывод программ в этом разделе меняется при каждом нажатии Run.
Чтобы получить целое число в диапазоне, растяните это значение, приведите его и сдвиньте. Для целого числа от min до max, оба включительно:
int value = (int) (Math.random() * (max - min + 1)) + min;
Вот как это работает для кубика, где min равно 1, а max равно 6:
Math.random() * 6даётdoubleот0.0до6.0, не включая6.0.(int)отбрасывает дробную часть, и получается одно из чисел0, 1, 2, 3, 4, 5.+ 1сдвигает их в1, 2, 3, 4, 5, 6.
Первая строка показывает пять случайных бросков. Вторая проверяет десять тысяч бросков и на практике всегда печатает lowest: 1, highest: 6: формула достигает обоих концов диапазона и никогда за них не выходит.
Скобки вокруг Math.random() * (max - min + 1) важны. Приведение применяется к значению сразу после него, поэтому (int) Math.random() * 6 сначала приводит Math.random(). Это всегда 0, а 0 * 6 равно 0, так что каждый «бросок» даёт одно и то же.
Для игр и упражнений Math.random() вполне подходит. Для более серьёзных задач класс java.util.Random и ThreadLocalRandom.current().nextInt(min, max + 1) (из java.util.concurrent) сразу возвращают целые числа, а Random может принимать seed, чтобы повторять одну и ту же последовательность в тестах. Ни один из них не подходит для паролей и токенов безопасности: для этого используйте java.security.SecureRandom.
Math.PI и Math.E
Math.PI (π) и Math.E (число Эйлера e) это константы static final double:
Используйте их вместо того, чтобы писать 3.14. Они настолько точны, насколько позволяет double, а имя сообщает читателю, что это за число.
Целый результат и результат double
Большинство методов Math принимают и возвращают double. Когда вы передаёте им значения int, Java автоматически расширяет аргументы до double, но арифметика, которую вы пишете до вызова, всё равно выполняется в int. Именно отсюда берётся большинство неверных ответов:
items / perBox это 7 / 2, а деление двух значений int отбрасывает остаток, поэтому получается 3 ещё до того, как Math.ceil его увидит. Math.ceil(3.0) равно 3.0. Сделайте один из операндов double, приведением или литералом вроде 4.0, чтобы деление сохранило дробную часть. Целочисленное деление подробнее объяснено на странице про операторы.
Общее правило: решите, какой тип вам нужен в конце, выполняйте деление или умножение в double, когда дробная часть важна, и приводите обратно к int или long только один раз, в самом конце.
Другие полезные методы
Ещё несколько методов того же класса, все вызываются так же:
Math.logэто натуральный логарифм,Math.log10логарифм по основанию 10.Math.floorMod(a, b)даёт остаток со знакомb, а это как раз то, что нужно, когда значение должно «оборачиваться» по кругу, например по дням недели. Оператор%сохраняет знакa.- Тригонометрические методы (
sin,cos,tan) принимают радианы. Сначала переведите градусы черезMath.toRadians. Math.addExact,Math.multiplyExactи родственные им методы при переполнении выбрасываютArithmeticException, а не молча переходят к отрицательному числу.
Часто задаваемые вопросы
Как пользоваться Math.pow в Java?
Math.pow(base, exponent) возвращает base в степени exponent как double, поэтому Math.pow(2, 3) равно 8.0. Чтобы сохранить результат в int, приведите его: int n = (int) Math.pow(2, 10); даёт 1024. Оператора возведения в степень ^ в Java нет: ^ это побитовое исключающее ИЛИ (XOR).
Как получить случайное число в диапазоне через Math.random?
Math.random() возвращает double от 0.0 включительно до 1.0 не включительно. Для целого числа от min до max включительно используйте (int) (Math.random() * (max - min + 1)) + min. Бросок кубика: (int) (Math.random() * 6) + 1.
Нужно ли импортировать класс Math в Java?
Нет. Math находится в пакете java.lang, который каждый файл Java импортирует автоматически. Все его методы static, поэтому они вызываются через имя класса, как Math.sqrt(16), без создания объекта.
Почему Math.round возвращает long в Java?
Math.round(double) возвращает long, потому что double может хранить значения гораздо больше, чем помещается в int. Чтобы присвоить результат int, нужно приведение: int n = (int) Math.round(2.6);. Math.round(float) возвращает int.
Чем отличаются Math.floor, Math.ceil и Math.round?
Math.floor округляет вниз (2.7 становится 2.0, -2.3 становится -3.0), Math.ceil округляет вверх (2.1 становится 3.0), а Math.round округляет до ближайшего целого, причём половины округляются вверх (2.5 становится 3). floor и ceil возвращают double, round возвращает long.