Перейти к содержимому
Теория · Операторы и выражения · урок 1 из 8

Арифметика и целое деление

Чему вы научитесь

Чему вы научитесь:

  • предсказывать результат целого деления и остатка, в том числе для отрицательных чисел;
  • переводить число из одного типа в другой и понимать, когда нужно приведение (int);
  • замечать переполнение int и защищаться от него;
  • склеивать строки с числами и печатать числа по шаблону через String.format.

Java считает как калькулятор, но у этого калькулятора свои правила. Главное из них: он помнит тип каждого числа, целое оно или дробное.

Операторы +, - и * работают с целыми числами как в школьной арифметике. С делением иначе: если оба числа имеют тип int, то и результат будет int, а дробной части у int нет.

Представьте, что вы раздаёте конфеты детям. Резать конфеты нельзя, поэтому каждый получает целое число штук, а лишние остаются у вас. Так и работает деление целых чисел:

JAVA
public class Main {
    public static void main(String[] args) {
        int sweets = 17;
        int kids = 5;
        System.out.println(sweets / kids); // 3
        System.out.println(sweets % kids); // 2
    }
}

Давайте посмотрим, что напечатала программа:

  1. sweets / kids печатает 3: семнадцать конфет на пятерых — по три каждому. Оператор / дал частное.
  2. sweets % kids печатает 2: две конфеты остались у вас. Оператор % дал остаток.

Обычный калькулятор показал бы 3.4, а программа напечатала 3. Картинка с конфетами хорошо работает для положительных чисел. Для отрицательных у Java своё правило, о нём — в разделе про остаток.

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

В Java пять арифметических операторов:

  • + — сложение;
  • - — вычитание;
  • * — умножение;
  • / — деление;
  • % — остаток от деления.

Порядок действий как в школе: *, / и % выполняются раньше + и -, а операторы одного уровня — слева направо. Поэтому 2 + 3 * 4 равно 14, а (2 + 3) * 4 равно 20: скобки меняют порядок.

Целое деление

Деление двух целых чисел называют целым делением: дробная часть результата отбрасывается, а не округляется.

  • 17 / 5 равно 3, хотя на бумаге получается 3.4.
  • 19 / 5 тоже равно 3, хотя 3.8 ближе к четырём.
  • -17 / 5 равно -3, а не -4: у отрицательного результата дробь тоже отбрасывается.

Получается, что целое деление всегда сдвигает результат к нулю: положительный вниз, отрицательный вверх.

Дробь получится, если хотя бы одно из двух чисел дробное. 7.0 / 2 и 7 / 2.0 дают 3.5: число с точкой имеет тип double, и деление становится обычным.

Остаток и его знак

Остаток — то, что осталось после целого деления. Его даёт оператор %, и с частным его связывает правило: a / b * b + a % b всегда равно a.

Из этого правила следует знак остатка. Он совпадает со знаком делимого, то есть левого числа:

JAVA
System.out.println(-17 / 5); // -3
System.out.println(-17 % 5); // -2
System.out.println(17 % -5); // 2

Разберём строки:

  1. -17 / 5 печатает -3: дробь отброшена в сторону нуля.
  2. -17 % 5 печатает -2. Частное равно -3, а -3 * 5 даёт -15. До -17 не хватает ещё -2, это и есть остаток.
  3. 17 % -5 печатает 2. Делимое 17 положительное, поэтому и остаток положительный, хотя делитель отрицательный.

Этот вопрос часто задают на собеседовании: какой знак у остатка, если делимое отрицательное? В математике остаток обычно считают неотрицательным, а в Java он берёт знак делимого.

Деление на ноль

Что случится при делении на ноль, зависит от типа чисел:

JAVA
int boxes = 0;
System.out.println(12.0 / boxes); // Infinity
System.out.println(12 / boxes);
TEXT
Exception in thread "main" java.lang.ArithmeticException: / by zero

Дробное деление: Infinity

12.0 / boxes — дробное деление, и Java не считает его ошибкой. Результат — особое значение double, бесконечность, и программа печатает Infinity.

Целое деление: исключение

У 12 / boxes результата нет. Программа останавливается на этой строке и печатает сообщение выше. Ошибку, которая случилась во время работы программы, называют исключением, а ArithmeticException — его имя.

Даже деление на литерал, например 12 / 0, компилятор ошибкой не считает: программа скомпилируется, а исключение случится при запуске.

Частая ошибка

Результат деления двух int кладут в double в надежде получить дробь:

JAVA
public class Main {
    public static void main(String[] args) {
        int total = 5;
        int count = 2;
        double average = total / count; // ✗
        System.out.println(average);    // 2.0
    }
}

Компилятор ошибки не видит, и программа печатает 2.0. Сначала Java выполняет total / count как целое деление и получает 2. Только потом это 2 становится 2.0, чтобы поместиться в double. Чтобы получить 2.5, одно из чисел должно быть дробным ещё до деления: например, объявите total как double.

Главное

  • Деление двух целых отбрасывает дробную часть: 17 / 5 — это 3, а -17 / 5 — это -3.
  • Оператор % даёт остаток, и его знак совпадает со знаком делимого: -17 % 5 — это -2.
  • Дробь получается, только если хотя бы одно из чисел дробное ещё до деления.
  • Целое деление на ноль бросает ArithmeticException, а дробное даёт Infinity.