Math.abs: примеры (JAVA)
Math.abs(int a): intОписание Math.abs()
Метод Math.abs() возвращает абсолютное (модульное) значение числового аргумента. Он определён в классе java.lang.Math и имеет перегрузки для типов int, long, float и double. Применяется при вычислении расстояний, отклонений, норм, при сравнении по модулю и в иных задачах, где требуется неотрицательное значение исходного числа.
Подписи методов:
public static int abs(int a)public static long abs(long a)public static float abs(float a)public static double abs(double a)
Возвращаемые значения и особенности:
- Для
intиlongвозвращается неотрицательное целое значение, равное модулю аргумента, за исключением граничного случая: дляInteger.MIN_VALUEилиLong.MIN_VALUEрезультат равен самому минимальному значению (переполнение), поскольку положный эквивалент не помещается в тип. - Для
floatиdoubleрезультат соответствует IEEE 754:NaNостаётсяNaN, знак отрицательного нуля исчезает (возвращается положительный ноль), положительная и отрицательная бесконечности переходят в положительную бесконечность. - Тип возвращаемого значения совпадает с типом аргумента.
Альтернативная реализация с детерминированным поведением представлена в StrictMath.abs(), однако для этих простых операций различия редко заметны. Для больших чисел используются классы BigInteger и BigDecimal с методом abs().
Короткие примеры использования
Ниже несколько примеров для всех перегрузок и особых случаев.
Пример с int:
public class A {
public static void main(String[] args) {
System.out.println(Math.abs(-5));
System.out.println(Math.abs(5));
System.out.println(Math.abs(Integer.MIN_VALUE));
}
}
5 5 -2147483648
Пример с long:
public class B {
public static void main(String[] args) {
System.out.println(Math.abs(-123456789012345L));
System.out.println(Math.abs(Long.MIN_VALUE));
}
}
123456789012345 -9223372036854775808
Пример с float и double (включая NaN и -0.0):
public class C {
public static void main(String[] args) {
System.out.println(Math.abs(-3.14f));
System.out.println(Math.abs(Double.NaN));
System.out.println(Math.abs(-0.0));
}
}
3.14 NaN 0.0
Похожие возможности в Java
Короткая сводка альтернатив и смежных средств в экосистеме Java:
- StrictMath.abs() - та же логика, но с детерминированной реализацией, полезна при требовании точной воспроизводимости между JVM.
- BigInteger.abs() и BigDecimal.abs() - используются для произвольно больших целых и точной десятичной арифметики, когда требуется избежать переполнения целых типов.
- Явная конструкция с условием, например
a < 0 ? -a : a, функционально эквивалентна, но может давать переполнение для минимального значения; редко предпочтительна перед встроенными перегрузками.
Рекомендации: при работе с большими значениями или финансовыми вычислениями предпочтение отдаётся BigInteger/BigDecimal. Для требуемой платформенной детерминированности - StrictMath. Для общих задач стандартный Math.abs обычно удобнее.
Эквиваленты в других языках
Краткий обзор аналогов и их отличий от Java:
- JavaScript:
Math.abs(x). Тип числа -Number(64‑битное с плавающей точкой). На-0возвращает0. Пример:console.log(Math.abs(-5)); console.log(Math.abs(-0));5 0
- Python: встроенная функция
abs(x). Поддерживает целые произвольной точности, поэтому переполнение отсутствует:print(abs(-10)) print(abs(-2**100))10 1267650600228229401496703205376
- PHP:
abs($x). Поддерживает int/float. Пример:echo abs(-3);3
- SQL: функция
ABS(value)в большинстве СУБД (Postgres, MySQL, SQL Server). Пример:SELECT ABS(-7) AS val;val ----- 7
- C#/.NET:
Math.Abs()перегружен для целых и чисел с плавающей точкой. Отличие: при попытке взять абсолютное значениеInt32.MinValueв некоторых реализациях может возникатьOverflowException(в проверяемом контексте) или результат сохранить минимальное значение; поведение зависит от платформы и версии .NET. - Go: пакет
mathпредоставляетmath.Abs(float64)только дляfloat64, для целых требуется конвертация/собственная реализация. Пример:fmt.Println(math.Abs(-3.5))3.5
- Lua:
math.abs(x), обычное поведение для чисел (как правило, double под капотом). - Kotlin:
kotlin.math.abs()и свойствоabsoluteValueу числовых типов. На JVM вызывает соответствующие реализации Java; для мультиплатформых целей поведение может зависеть от целевой платформы.
Ключевые отличия от Java: наличие произвольной точности в Python, отсутствие перегрузок для целых типов в Go, различия в обработке граничных целых значений в .NET, и нюансы с представлением чисел с плавающей точкой в разных рантаймах.
Типичные ошибки при использовании
- Ожидание исключения при переполнении целых типов. Пример:
public class E {
public static void main(String[] args) {
System.out.println(Math.abs(Integer.MIN_VALUE));
}
}
-2147483648
Комментарий: метод не бросает исключение, а возвращает отрицательное значение из-за отсутствия положительного представления.
- Игнорирование
NaNдля float/double. Пример:
public class F {
public static void main(String[] args) {
System.out.println(Math.abs(Double.NaN));
}
}
NaN
Комментарий: проверка на NaN нужна, если далее выполняются сравнения или агрегирование.
- Ошибки с
nullпри использовании обёрток (Integer,Long): передачаnullвызываетNullPointerException. - Ожидание особой обработки
-0.0без явной проверки:Math.abs(-0.0)даёт0.0, но знак нуля может быть важен при побитовых проверках. - Использование
Math.absвместоMath.floorModдля вычисления положительного остатка от деления отрицательных чисел - логика отличается.
Изменения и стабильность реализации
Метод Math.abs() стабилен с ранних версий Java. Изменений в семантике для существующих перегрузок не происходило в современных версиях платформы. Для гарантированной платформенно-независимой реализации оставался и остаётся класс StrictMath. Новые возможности в области больших чисел (например, улучшения производительности в BigInteger/BigDecimal) не изменяют поведение Math.abs.
Расширенные и редкие примеры
Ниже несколько практических и менее распространённых приёмов.
1) Безопасный абсолют для int, возвращающий long, чтобы избежать переполнения:
public class SafeAbs {
public static long safeAbs(int x) {
return x == Integer.MIN_VALUE ? (long)Integer.MAX_VALUE + 1 : Math.abs(x);
}
public static void main(String[] args) {
System.out.println(safeAbs(-5));
System.out.println(safeAbs(Integer.MIN_VALUE));
}
}
5 2147483648
Пояснение: возвращается long, чтобы корректно представить абсолютное значение минимального int.
2) Сортировка по абсолютному значению массива целых:
import java.util.*;
public class SortByAbs {
public static void main(String[] args) {
Integer[] a = { -3, 1, -2, 4 };
Arrays.sort(a, Comparator.comparingInt(Math::abs));
System.out.println(Arrays.toString(a));
}
}
[1, -2, -3, 4]
3) Нахождение медианы абсолютных отклонений (Median Absolute Deviation):
import java.util.*;
public class MAD {
public static double mad(double[] data) {
double median = median(data);
double[] dev = new double[data.length];
for (int i = 0; i < data.length; i++) dev[i] = Math.abs(data[i] - median);
return median(dev);
}
private static double median(double[] d) {
double[] copy = Arrays.copyOf(d, d.length);
Arrays.sort(copy);
int m = copy.length/2;
return (copy.length % 2 == 0) ? (copy[m-1]+copy[m])/2.0 : copy[m];
}
public static void main(String[] args) {
double[] v = {1.0, 2.0, 5.0, 7.0, 9.0};
System.out.println(mad(v));
}
}
2.0
4) Работа с BigInteger для больших значений:
import java.math.BigInteger;
public class BigAbs {
public static void main(String[] args) {
BigInteger b = new BigInteger("-123456789012345678901234567890");
System.out.println(b.abs());
}
}
123456789012345678901234567890
5) Обнаружение отрицательного нуля у double (редкий кейс):
public class NegZero {
public static boolean isNegativeZero(double d) {
return Double.doubleToRawLongBits(d) == Double.doubleToRawLongBits(-0.0d);
}
public static void main(String[] args) {
double z = -0.0;
System.out.println(Math.abs(z));
System.out.println(isNegativeZero(z));
}
}
0.0 true
6) Использование в потоках и коллекциях (пример с Java Streams):
import java.util.*;
import java.util.stream.*;
public class StreamAbsSum {
public static void main(String[] args) {
List list = Arrays.asList(-1, -2, 3, 4);
int sum = list.stream().mapToInt(Math::abs).sum();
System.out.println(sum);
}
}
10
7) Применение в численных методах: нормализация вектора по L1 норме:
public class Normalize {
public static double[] normalizeL1(double[] v) {
double sum = 0;
for (double x : v) sum += Math.abs(x);
if (sum == 0) return v.clone();
double[] r = new double[v.length];
for (int i = 0; i < v.length; i++) r[i] = v[i] / sum;
return r;
}
public static void main(String[] args) {
double[] v = {-1, 2, -3};
double[] n = normalizeL1(v);
for (double x : n) System.out.printf("%.4f ", x);
}
}
-0.1667 0.3333 -0.5000
Эти примеры демонстрируют, как учесть границы типов и особенности чисел с плавающей точкой при практическом применении Math.abs().