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

Арифметика

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

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

  • предсказывать результат деления и остатка целых чисел, в том числе отрицательных;
  • объяснять, что происходит, когда число не помещается в свой тип, и зачем нужен &+;
  • сравнивать значения и объединять условия через &&, || и !;
  • проверять, попадает ли число в диапазон, и выбирать одно из двух значений оператором ? :.
Семнадцать конфет разложены по пяти банкам по три, две остались на блюдце; надписи 17 / 5 и 17 % 5

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

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

SWIFT
let sweets = 17
let kids = 5
print(sweets / kids) // 3
print(sweets % kids) // 2

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

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

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

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

Значок действия, например +, называют оператором. Для чисел в Swift их пять:

  • + складывает: 7 + 2 — это 9;
  • - вычитает: 7 - 2 — это 5;
  • * умножает: 7 * 2 — это 14;
  • / делит: 7 / 2 — это 3;
  • % даёт остаток от деления: 7 % 2 — это 1.

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

Деление целых чисел

Когда оба числа имеют тип Int, результат тоже получается Int, а у Int нет дробной части. Такое деление называют целочисленным: дробная часть результата отбрасывается, а не округляется.

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

Целочисленное деление всегда сдвигает результат к нулю. Так же в прошлой теме Int(2.9) превращался в 2, а Int(-2.9) — в -2.

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

Оператор % даёт то, что осталось после целочисленного деления. Частное и остаток связаны: частное, умноженное на делитель, плюс остаток дают исходное число. Для конфет это 3 * 5 + 2, то есть 17.

Из этой связи следует правило для отрицательных чисел: знак остатка совпадает со знаком делимого, числа слева от %.

SWIFT
print(-17 / 5, -17 % 5) // -3 -2
print(17 / -5, 17 % -5) // -3 2

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

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

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

Оператор % работает только с целыми числами. Если применить его к Double, компилятор выдаст ошибку.

Дробный результат

Дробь получается, когда делят числа типа Double. Есть два способа её получить.

Дробное число в коде

Число с точкой, например 7.0, уже дробное. Число 2 рядом с ним Swift тоже прочитает как Double, и 7.0 / 2 даст 3.5.

Преобразование констант

У константы тип уже есть, и сам он не меняется. Поэтому оба числа переводят в Double до деления: Double(sweets) / Double(kids) даёт 3.4.

Составное присваивание

Запись score = score + 5 встречается так часто, что для неё есть сокращение: score += 5. Такие операторы называют составным присваиванием.

SWIFT
var score = 10
score += 5
score -= 3
score *= 2
print(score) // 24

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

  1. score += 5 прибавляет 5: в score теперь 15.
  2. score -= 3 вычитает 3: теперь там 12.
  3. score *= 2 умножает на 2: теперь там 24.
  4. print(score) печатает 24.

Составное присваивание меняет переменную, поэтому работает только с var.

Привычной по другим языкам записи score++ в Swift нет:

TEXT
error: cannot find operator '++' in scope; did you mean '+= 1'?

Компилятор сам подсказывает замену: score += 1.

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

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

SWIFT
let total = 7
let parts = 2
let wrong = Double(total / parts) // ✗
let right = Double(total) / Double(parts) // ✓
print(wrong, right) // 3.0 3.5

Ошибки компиляции нет, но в wrong оказывается 3.0. Сначала выполняется total / parts, то есть целочисленное деление, и только его результат 3 становится Double. Переводить в Double нужно числа до деления, как в строке с right.

Главное

  • Деление двух Int отбрасывает дробную часть: 17 / 5 — это 3, а -17 / 5 — это -3.
  • % даёт остаток, и его знак совпадает со знаком делимого: -17 % 5 — это -2.
  • Чтобы получить дробь, в Double переводят числа до деления, а не результат.
  • +=, -= и *= меняют переменную на месте, а оператора ++ в Swift нет.