Зачем компьютеру разные типы чисел
В жизни вы не путаете «штуки» и «граммы»: пять яблок и пять с половиной килограммов — это разные по природе величины, и складывать их напрямую бессмысленно. У чисел в программе то же самое: одни числа всегда целые (количество товаров, номер строки, счётчик), а другие — дробные (цена, вес, средний балл). Swift различает эти два случая на уровне типов и не даёт случайно перепутать одно с другим — это и убережёт вас от ошибок, и первое время будет немного раздражать. В этом уроке разберём основные числовые типы, логический тип Bool и то, как вставлять значения переменных прямо в текст.
Int, Double и их младшие родственники
Целые числа в Swift имеют тип Int: это количество, номер, индекс — всё, что не бывает дробным по смыслу.
let studentsCount: Int = 24
let floor = -2
print(studentsCount)
Дробные числа получают тип Double — это основной тип для чисел с плавающей точкой в Swift, используется почти везде: цены, координаты, проценты.
let price: Double = 149.90
let average = 4.75
print(price)
Есть ещё Float — тоже дробное число, но с меньшей точностью и меньшим расходом памяти. На практике в обычных приложениях почти всегда берут Double, а Float нужен редко, например для очень больших объёмов данных или там, где важна каждая единица памяти. Пока достаточно знать, что такой тип существует и выглядит он так же, как Double, только с явной аннотацией: let rating: Float = 4.5.
Символ — это тип Character, он хранит ровно один печатаемый символ (букву, цифру, знак) и записывается через двойные кавычки, как строка:
let grade: Character = "A"
let sign: Character = "!"
Если попробовать положить в Character несколько символов, компилятор откажется: этот тип рассчитан строго на один символ. Про строки и работу с текстом целиком поговорим отдельно, здесь Character упомянут только как сосед по семье базовых типов.
Читаемые литералы
Когда число длинное, его тяжело читать глазами: 1000000 — это миллион или сто тысяч, сходу не разберёшь. Swift разрешает вставлять подчёркивания между цифрами — компилятор их просто игнорирует, а человеку читать становится сильно проще:
let population: Int = 1_000_000
let price: Double = 12_345.67
Кроме привычной десятичной записи, целые числа можно писать в двоичной форме с префиксом 0b и в шестнадцатеричной с префиксом 0x. Это пригодится в будущем при работе с байтами и цветами, а пока достаточно узнавать такую запись:
let binaryFlags = 0b1010 // это число 10
let colorCode = 0xFF // это число 255
Swift не смешивает типы молча
Вот здесь начинается самое важное. В некоторых языках можно сложить целое число и дробное, и язык сам «дотянет» одно до другого. Swift так не делает — и не потому, что придирается, а потому что при таком автоматическом преобразовании легко незаметно потерять точность или получить не то поведение, которого вы ждали. Поэтому компилятор требует явного преобразования типов.
let itemsCount: Int = 3
let pricePerItem: Double = 2.5
// let total = itemsCount + pricePerItem // ошибка компиляции
let total = Double(itemsCount) * pricePerItem
print(total)
Строка Double(itemsCount) — это не «превращение» переменной, а создание нового значения типа Double из значения itemsCount. Сама переменная itemsCount так и остаётся Int. Именно такое явное преобразование Swift требует каждый раз, когда вы смешиваете Int и Double в одном выражении — сложении, вычитании, умножении или делении.
Целочисленное деление — главная ловушка новичка
Деление — тот случай, где типы решают всё. Если оба числа — Int, результат деления тоже будет Int, и дробная часть просто отбрасывается, без округления:
let a = 7
let b = 2
print(a / b)
Здесь напечатается 3, а не 3.5: деление целых чисел в Swift называется целочисленным, и половина между 3 и 4 никуда не округляется — она просто теряется. Если хотя бы одно из чисел — Double, результат тоже становится Double, и дробная часть сохраняется:
print(7.0 / 2)
Тут результат — 3.5. Обратите внимание: 2 здесь без точки, но так как второй операнд 7.0 уже Double, Swift сам подбирает подходящий тип для литерала 2 — конкретно для числовых литералов без переменной это разрешено, в отличие от сложения двух уже существующих переменных разных типов. Если же оба значения хранятся в переменных типа Int, а вам нужен точный дробный результат, переводите в Double явно, как в примере с преобразованием выше.
Остаток от деления
Оператор % возвращает остаток от целочисленного деления — пригождается, чтобы проверить чётность числа, разложить секунды на минуты или распределить элементы по группам:
let seconds = 130
let minutes = seconds / 60
let leftoverSeconds = seconds % 60
print(minutes)
print(leftoverSeconds)
130 секунд — это 2 полных минуты (130 / 60) и ещё 10 секунд остатка (130 % 60). Деление и остаток почти всегда идут в паре именно так.
Строковая интерполяция
Чтобы вставить значение переменной прямо в текст, не нужно склеивать строки — используется интерполяция: внутри строки пишете обратный слэш, круглые скобки, а в них — что угодно, что можно вычислить.
let name = "Аня"
let age = 21
print("Привет, \(name)! Тебе \(age) лет.")
Важно, что внутри скобок необязательно должна быть просто переменная — это может быть целое выражение, которое Swift вычислит на месте перед тем, как собрать строку:
let width = 5
let height = 3
print("Площадь: \(width * height)")
Здесь Swift сначала посчитает width * height, получит 15, а затем подставит результат в строку — переменная с промежуточным значением для этого не нужна.
Bool и условия
Bool — логический тип с ровно двумя значениями: true и false. Он отвечает на вопросы вида «да или нет», «выполнено условие или нет»:
let isRegistered: Bool = true
let hasDiscount = false
print(isRegistered)
Ключевая особенность Swift: условие в конструкции if обязано быть именно значением типа Bool, и никак иначе. В некоторых языках вместо условия можно подставить число, и ноль считается «ложью», а всё остальное — «правдой». В Swift так не работает:
let attemptsLeft = 1
// if attemptsLeft { ... } // ошибка компиляции: Int — не Bool
if attemptsLeft > 0 {
print("Можно ещё попробовать")
}
Оператор > из последнего примера и другие способы получить Bool из сравнения разберём отдельно и подробно — здесь достаточно запомнить само правило: условие — это всегда Bool, число вместо него компилятор не примет ни при каких обстоятельствах.
Частые ошибки
- Попытка сложить
IntиDoubleнапрямую — компилятор потребует обернуть целое число вDouble(...). - Ожидание, что
7 / 2даст3.5— если оба числаInt, дробная часть отбрасывается, получится3. - Забыть, что для дробного результата достаточно, чтобы
Double-типом был хотя бы один из операндов, но если оба операнда — переменные типаInt, преобразовывать нужно явно. - Пытаться использовать число как условие в
if— в Swift сработает только настоящийBool. - Забыть закрывающую скобку в интерполяции
\(...)— компилятор укажет на ошибку синтаксиса строки.
Резюме
Int— целые числа,Double— дробные,Bool— логическое да/нет,Character— один символ,Float— редко используемая дробная альтернатива с меньшей точностью.- В больших числах можно ставить подчёркивания для читаемости:
1_000_000; есть также двоичная (0b) и шестнадцатеричная (0x) запись. - Swift не складывает
IntиDoubleмолча — нужен явныйDouble(x), это защита от потери точности, а не прихоть языка. - Деление двух
Intцелочисленное:7 / 2даёт3; чтобы получить3.5, хотя бы одно значение должно бытьDouble. - Оператор
%возвращает остаток от деления. - Интерполяция
\(...)вставляет в строку значение и может содержать целое выражение, а не только имя переменной. - Условие в
ifобязано быть типомBool— число вместо него не подходит.
Проверьте себя
4 вопроса
Стоимость подписки
Напишите программу, которая объявляет количество месяцев подписки как значение типа Int, равное 6, и цену одного месяца как значение типа Double, равное 4.5. Посчитайте полную стоимость подписки, явно преобразовав количество месяцев в Double перед умножением, и напечатайте результат одной командой print.
Программа должна вывести ровно: 27.0
Яблоки по коробкам
Есть 17 яблок, а в одну коробку помещается 5 яблок. Объявите обе величины как Int, а затем одной строкой print с интерполяцией выведите, сколько получится полных коробок и сколько яблок останется. Деление и остаток нужно посчитать прямо внутри интерполяции — без промежуточных переменных для результата деления и остатка.
Программа должна вывести ровно: Целых коробок: 3, свободных яблок: 2