W3docs

Арифметические операторы Java

Операторы +, -, *, /, % в Java: целочисленное деление, приоритет операторов и особенности чисел с плавающей точкой.

В Java есть пять арифметических операторов: сложение, вычитание, умножение, деление и остаток от деления. Их синтаксис такой же, как в C, JavaScript или Python, однако статическая типизация Java создаёт несколько неочевидных ситуаций, связанных с делением и переполнением, о которых стоит знать прежде, чем начинать вычисления.

На этой странице рассмотрены все пять операторов, объясняется, почему целочисленное деление усекает результат, как ведёт себя % с отрицательными числами, каков приоритет операторов, что делают сокращения ++/--, что такое «тихое» целочисленное переполнение и почему числа с плавающей точкой могут давать неожиданные результаты. Полный список операторов Java см. в обзоре Java Operators.

Пять операторов

int a = 14;
int b = 4;

System.out.println(a + b);  // 18
System.out.println(a - b);  // 10
System.out.println(a * b);  // 56
System.out.println(a / b);  // 3   — integer division
System.out.println(a % b);  // 2   — remainder

Целочисленное деление усекает результат

Если оба операнда / являются целыми числами, результат также будет целым — дробная часть отбрасывается (усечение в сторону нуля):

System.out.println(7 / 2);    // 3, not 3.5
System.out.println(-7 / 2);   // -3
System.out.println(1 / 3);    // 0

Чтобы получить вещественный результат, хотя бы один из операндов должен иметь тип с плавающей точкой. Можно записать литерал как double (7.0) или привести int к double:

System.out.println(7.0 / 2);        // 3.5
System.out.println(7 / 2.0);        // 3.5
System.out.println((double) 7 / 2); // 3.5

Приведение типа имеет более высокий приоритет, чем /, поэтому (double) 7 / 2 сначала приводит 7 к double, а затем выполняет деление — результат 3.5. Будьте осторожны с (double) (7 / 2): сначала выполняется целочисленное деление, и вы получите 3.0.

Это частая ловушка для начинающих. Если вы видите 0 там, где ожидали ненулевое частное, — скорее всего, виновато целочисленное деление.

Оператор остатка %

% возвращает остаток от целочисленного деления. Он определён так, что (a / b) * b + (a % b) == a:

System.out.println(10 % 3);    // 1
System.out.println(-10 % 3);   // -1  — sign matches the dividend
System.out.println(10 % -3);   // 1

Типичные применения:

  • Проверка делимости: if (n % 2 == 0) проверяет чётность.
  • Циклическая индексация: arr[(i + 1) % arr.length] возвращается к 0 после последнего элемента.
  • Выделение цифр или единиц: n % 10 — последняя цифра числа; seconds % 60 — секунды в пределах минуты.

Другие числовые функции — возведение в степень, округление, квадратный корень — доступны через Java Math Class.

% также работает с double, где возвращает остаток по стандарту IEEE 754. Для более точного управления можно использовать метод Math.IEEEremainder.

Приоритет операторов

Действуют стандартные правила:

  1. Сначала *, /, %
  2. Затем +, -
  3. Слева направо при одинаковом уровне приоритета
int result = 2 + 3 * 4;      // 14, not 20
int result2 = (2 + 3) * 4;   // 20
int result3 = 10 - 2 - 3;    // 5  — left-to-right

Если есть сомнения — ставьте скобки. Это ничего не стоит.

Инкремент и декремент — ++ и --

Унарные ++ и -- увеличивают или уменьшают значение переменной на 1:

int x = 5;
x++;     // x is 6
x--;     // x is 5

Они существуют в префиксной (++x) и постфиксной (x++) формах. Разница важна только внутри выражения:

int a = 5;
int b = a++;   // postfix: b is 5 (old value), a becomes 6
int c = ++a;   // prefix: a becomes 7, c is 7

Для наглядности рекомендуется использовать ++ и -- отдельной строкой, когда это возможно.

Переполнение происходит незаметно

Целочисленная арифметика для int и long при переполнении перекручивается — исключение не выбрасывается:

int max = Integer.MAX_VALUE;    // 2147483647
int wrapped = max + 1;          // -2147483648 (Integer.MIN_VALUE)

Если нужно обнаружение переполнения, используйте Math.addExact, Math.multiplyExact и другие методы, которые выбрасывают ArithmeticException при переполнении.

Особенности чисел с плавающей точкой

double соответствует стандарту IEEE 754 — быстрый и хорошо поддерживаемый, однако большинство десятичных дробей не может быть представлено им точно:

System.out.println(0.1 + 0.2);   // 0.30000000000000004

Это не ошибка Java — так работает двоичная арифметика с плавающей точкой. Для денежных расчётов, научной точности или любых вычислений, требующих точной десятичной арифметики, используйте BigDecimal:

import java.math.BigDecimal;

BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum);   // 0.3

(Всегда передавайте строку в new BigDecimal(...); new BigDecimal(0.1) по-прежнему захватит двоичную неточность.)

Демонстрация

java— editable, runs on the server

Что дальше

Java Assignment Operators=, += и семейство операторов составного присваивания.

Практика

Практика
Чему равно выражение (7 / 2) в Java?
Чему равно выражение (7 / 2) в Java?
Was this page helpful?