Math.abs: примеры (JAVA)

Абсолютное значение и особенности Math.abs()
Раздел: Математические операции
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, чтобы избежать переполнения:

Пример java
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) Сортировка по абсолютному значению массива целых:

Пример java
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):

Пример java
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 для больших значений:

Пример java
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 (редкий кейс):

Пример java
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):

Пример java
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 норме:

Пример java
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().

джава Math.abs function comments

En
Math.abs Возвращает абсолютное значение