Арифметика и целое деление
Чему вы научитесь:
- предсказывать результат целого деления и остатка, в том числе для отрицательных чисел;
- переводить число из одного типа в другой и понимать, когда нужно приведение
(int); - замечать переполнение
intи защищаться от него; - склеивать строки с числами и печатать числа по шаблону через
String.format.
Java считает как калькулятор, но у этого калькулятора свои правила. Главное из них: он помнит тип каждого числа, целое оно или дробное.
Операторы +, - и * работают с целыми числами как в школьной арифметике. С делением иначе: если оба числа имеют тип int, то и результат будет int, а дробной части у int нет.
Представьте, что вы раздаёте конфеты детям. Резать конфеты нельзя, поэтому каждый получает целое число штук, а лишние остаются у вас. Так и работает деление целых чисел:
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
}
}Давайте посмотрим, что напечатала программа:
sweets / kidsпечатает3: семнадцать конфет на пятерых — по три каждому. Оператор/дал частное.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.
Из этого правила следует знак остатка. Он совпадает со знаком делимого, то есть левого числа:
System.out.println(-17 / 5); // -3
System.out.println(-17 % 5); // -2
System.out.println(17 % -5); // 2Разберём строки:
-17 / 5печатает-3: дробь отброшена в сторону нуля.-17 % 5печатает-2. Частное равно-3, а-3 * 5даёт-15. До-17не хватает ещё-2, это и есть остаток.17 % -5печатает2. Делимое17положительное, поэтому и остаток положительный, хотя делитель отрицательный.
Этот вопрос часто задают на собеседовании: какой знак у остатка, если делимое отрицательное? В математике остаток обычно считают неотрицательным, а в Java он берёт знак делимого.
Деление на ноль
Что случится при делении на ноль, зависит от типа чисел:
int boxes = 0;
System.out.println(12.0 / boxes); // Infinity
System.out.println(12 / boxes);Exception in thread "main" java.lang.ArithmeticException: / by zeroДробное деление: Infinity
12.0 / boxes — дробное деление, и Java не считает его ошибкой. Результат — особое значение double, бесконечность, и программа печатает Infinity.
Целое деление: исключение
У 12 / boxes результата нет. Программа останавливается на этой строке и печатает сообщение выше. Ошибку, которая случилась во время работы программы, называют исключением, а ArithmeticException — его имя.
Даже деление на литерал, например 12 / 0, компилятор ошибкой не считает: программа скомпилируется, а исключение случится при запуске.
Частая ошибка
Результат деления двух int кладут в double в надежде получить дробь:
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.