JavaRush /Курсы /Swift SELF /Целые числа: Int, Int64, UInt

Целые числа: Int, Int64, UInt

Swift SELF
6 уровень , 1 лекция
Открыта

1. Все любят целые числа

Когда вы только начинаете программировать, очень хочется, чтобы существовал один тип Number, который «всё умеет». Но компьютер — существо экономное и слегка параноидальное: он хочет заранее знать, сколько памяти выделить под число, может ли там быть минус, и что делать, если вы попытаетесь записать туда «слишком большое» значение. Поэтому в Swift есть несколько целых типов, и каждый — про свой смысл и свои границы.

Представьте, что целое число — это коробка. Коробки бывают маленькие и большие. А ещё бывают коробки, на которых крупно написано «МИНУСЫ НЕ КЛАСТЬ». Если вы кладёте число не в ту коробку — компилятор или рантайм (или оба вместе) устраивают вам короткую образовательную беседу в виде ошибки.

Мысль дня: скорее всего вам нужен Int, и это не лень думать, а нормальная инженерная практика. Даже в официальной рекомендации по Swift подчёркивается: если вам не нужен строго фиксированный размер числа, используйте Int — так проще жить и меньше лишних преобразований типов.

2. Int — основной целочисленный тип

Int — это основной «рабочий» целочисленный тип в Swift. Он знаковый, то есть хранит и положительные, и отрицательные значения. Обычно Int выбирают для счётчиков, результатов вычислений, индексов, разницы между величинами и всего, что в жизни может уходить в минус (например, «температура на улице» или «изменение баланса»).

Важный нюанс: размер Int зависит от платформы (на большинстве современных компьютеров и телефонов он 64-битный, но в теории может быть и 32-битным). В учебных задачах чаще всего это не критично — но мысль «у числа есть границы» мы закрепим прямо сейчас.

Границы Int: Int.min и Int.max

У каждого целого типа есть минимальное и максимальное значение, которое он может хранить. В Swift это доступно как свойства типа.

import Foundation

print("Int.min =", Int.min)
print("Int.max =", Int.max)

Если вы запустите этот код, вы увидите реальные числа. И это хороший момент, чтобы осознать: тип — это контракт. Он не обещал вам «бесконечные числа», он обещал вам числа в конкретном диапазоне.

Читаемость больших чисел: разделители _

Когда вы посмотрели на Int.max, вы, скорее всего, увидели длинное число вроде:

9223372036854775807

Читать такие числа неудобно. Поэтому Swift разрешает вставлять в числах символ подчёркивания _, чтобы разделять разряды. Компилятор просто игнорирует эти символы.

Например:

let a = 9007199254740993
let b = 9_007_199_254_740_993

Для Swift это одно и то же число. Подчёркивания нужны только для удобства чтения.

Обычно их используют так же, как разделяют числа в математике — по тысячам:

let population = 8_000_000_000
let distance = 384_400
let secondsInDay = 86_400

Это никак не влияет на вычисления, но делает код гораздо понятнее. Особенно когда числа большие.

Мини-паттерн: проверяем, что число подходит по смыслу

Допустим, вы пишете программу, где пользователь вводит количество дней отпуска. Это точно не должно быть отрицательным, и, скажем, «10 миллионов дней отпуска» тоже выглядит подозрительно (если только вы не бессмертный эльф из отдела кадров).

import Foundation

let line = readLine() ?? "0"
let days = Int(line) ?? 0

if days < 0 {
    print("Дней отпуска не может быть меньше 0")
} else if days > 365 {
    print("Слишком много дней отпуска для одного года")
} else {
    print("Ок, отпуск: \(days) дней")
}

Здесь важна не цифра 365, а идея: границы бывают не только у типа, но и у предмета задачи. Int позволяет хранить огромные числа, но ваша задача может не позволять.

3. Другие целые типы: Int64 и UInt

Иногда Int действительно не лучший вариант — не потому что он «плохой», а потому что у задачи есть дополнительные требования: фиксированный формат, протокол, или чёткая модель данных «без минусов». В таких местах чаще всего всплывают Int64 и UInt.

Int64: фиксированный диапазон 64 бита

Int64 — это тоже знаковое целое число, но с фиксированным размером: ровно 64 бита. Почему это вообще бывает важно? Потому что иногда вы работаете с данными, у которых формат строго задан: например, число пришло из файла/протокола/сторонней системы, где «всегда 64-битное целое». Даже если ваш Int обычно тоже 64-битный, сам факт фиксированности иногда важнее удобства.

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

Границы Int64

import Foundation

print("Int64.min =", Int64.min)
print("Int64.max =", Int64.max)

По сути, это «большая коробка» для целых чисел с минусом.

Приведение типа

Иногда нужно превратить значение одного типа в другой. Например, число типа Int можно преобразовать в Int64. В Swift это делается с помощью конструктора типа.

let a: Int = 42
let b: Int64 = Int64(a)			//преобразовали знаение типа Int в тип Int64
let d : Double = Double(b) 	//преобразовали знаение типа Int64 в тип Double

Здесь Int64(a) означает: «создай число типа Int64, взяв значение из a». Такое преобразование называется приведением типа.

Мы будем ещё подробно говорить о приведении типов позже. Пока достаточно помнить простую идею: если в выражении участвуют числа разных типов, иногда нужно явно сказать компилятору, к какому типу привести значение.

Почему нельзя смешивать Int и Int64 без приведения

Swift очень строго относится к типам: если слева Int, а справа Int64, он не будет угадывать за вас, «как правильно». Это часто раздражает новичков, но на практике спасает от тихих ошибок.

import Foundation

let a: Int = 42
let b: Int64 = 100

let sum = Int64(a) + b
print("sum =", sum) // sum = 142

Обратите внимание на идею: мы выбрали “главный” тип выражения (Int64) и привели к нему второе число.

UInt: целые числа без минуса

UInt — это беззнаковое целое число: оно хранит только значения 0, 1, 2, … Казалось бы, удобно: «раз минуса нет — значит можно хранить больше положительных значений». Это правда. Но есть цена: вы не сможете просто так сделать «минус один», «разницу» или «уменьшить ниже нуля». И самое важное — вы часто будете упираться в преобразования типов, потому что Int и UInt нельзя смешивать без явного приведения.

Главная ошибка новичка: взять UInt «на всякий случай», а потом удивляться, почему вычитание и сравнения начинают превращаться в мини-квест.

Границы UInt

import Foundation

print("UInt.min =", UInt.min) // всегда 0
print("UInt.max =", UInt.max)

Безопасное превращение Int UInt

Преобразование UInt(someInt) имеет смысл только если someInt >= 0. Поэтому сначала — проверка, потом — конвертация.

import Foundation

let delta: Int = -3

if delta >= 0 {
    let u = UInt(delta)
    print("u =", u)
} else {
    print("delta is negative")
}

Это выглядит чуть длиннее, чем «просто привести тип», но зато код честный: вы явно говорите, что отрицательные значения — отдельный сценарий.

4. Переполнение: когда число не влезло

В математике числа бесконечны. В компьютере числа — как чемодан: если вы пытаетесь запихнуть туда ещё один свитер, чемодан либо не закрывается, либо закрывается, но потом вы не узнаете свой свитер (в зависимости от языка и режима). В Swift целочисленное переполнение в обычных операциях — это, как правило, ошибка выполнения: программа падает, потому что контракт типа нарушен.

Мы не будем сегодня изучать специальные операторы переполнения (это отдельная тема и отдельные грабли), но мы можем научиться избегать переполнения там, где оно реально возможно.

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

Представим, что у вас есть большое число a, и вы хотите прибавить b. Если a близко к Int.max, то a + b может выйти за границу. Проверка делается так: если a > Int.max - b, то складывать нельзя.

import Foundation

let a = Int.max
let b = 10

if a > Int.max - b {
    print("Слишком большое число: будет переполнение")
} else {
    print(a + b)
}

Этот паттерн выглядит как «немного математики», но он очень практичный: вы не даёте программе уйти в аварийный режим.

5. Как выбирать тип без лишней философии

Когда вы пишете учебные задачи, хочется угадать «идеально правильный тип». В реальном коде чаще нужен не идеальный, а разумный. Выбор типа — это баланс между смыслом данных, удобством вычислений и тем, как часто вам придётся делать преобразования.

Пока вы новичок, можно держать в голове простую модель: Int — ваш дефолт. UInt — только когда вы реально уверены, что минуса быть не может и это упрощает модель данных (а не усложняет). Int64 — когда нужен фиксированный 64-битный формат или реально большие значения.

Таблица «что когда брать»

Тип Есть минус? Размер Когда выбирать по смыслу Типичная цена ошибки
Int
Да платформенный почти всегда «по умолчанию» обычно минимальная
Int64
Да 64 бита фиксированный формат / очень большие числа лишние преобразования, если всё вокруг Int
UInt
Нет платформенный натуральные величины (0+) и вы уверены, что минуса не будет боль с вычитанием и конвертациями

И отдельно важная ремарка: даже если число «по смыслу не отрицательное», это не означает, что вы обязаны брать UInt. В рекомендациях по Swift прямо отмечается, что Int удобнее и предпочтительнее как единый тип, даже для неотрицательных значений, если нет особой причины.

Мини-блок-схема выбора

flowchart TD
    A["Нужно хранить целое число"] --> B{"Может быть минус?"}
    B -- "Да" --> C{"Нужен фиксированный 64-битный формат?"}
    C -- "Да" --> D["Берём Int64"]
    C -- "Нет / не уверен" --> E["Берём Int"]
    B -- "Нет" --> F{"Есть сильная причина брать UInt?"}
    F -- "Да, точно 0+ и это упрощает модель" --> G["Берём UInt"]
    F -- "Нет / сомневаюсь" --> E["Берём Int"]

Смысл схемы простой: если сомневаетесь — Int. Это тот редкий случай, когда «сомневаюсь» — отличная инженерная стратегия.

6. Пример: маленькое CLI-приложение «Шагомер»

Чтобы не было ощущения, что типы — это чистая теория, давайте продолжим строить наше простое консольное приложение. Пусть это будет мини-«шагомер»: пользователь вводит количество шагов за день, а программа аккуратно валидирует ввод и хранит «итог» как неотрицательное число.

Мы пока не используем массивы и функции (они будут позже), поэтому сделаем один «цикл на несколько вводов» и один общий итог.

Идея модели данных

Количество шагов по смыслу не может быть отрицательным, поэтому хранить итог логично в UInt. Но ввод пользователя мы читаем строкой и превращаем в Int, потому что так проще ловить «минусы» и ошибки. Затем, только если всё хорошо, переводим в UInt и прибавляем к итогу.

Мини-версия: один ввод

import Foundation

var totalSteps: UInt = 0

print("Сколько шагов вы прошли сегодня?")
let line = readLine() ?? "0"
let stepsInt = Int(line) ?? 0

if stepsInt < 0 {
    print("Шаги не могут быть отрицательными")
} else {
    let steps = UInt(stepsInt)
    totalSteps += steps
    print("Итого шагов: \(totalSteps)")
}

Здесь мы сделали важную вещь: UInt появляется только после проверки. Это не «лишний код», а честная защита от некорректных данных.

Несколько вводов через цикл for-in

Пусть пользователь вводит шаги за 3 дня, а мы суммируем. Это уже похоже на реальную задачу: в цикле легко случайно «улететь» в переполнение, но для шагов это маловероятно. Всё равно приятно помнить, что тип имеет max.

import Foundation

var totalSteps: UInt = 0

for day in 1...3 {
    print("День \(day). Шаги:")
    let line = readLine() ?? "0"
    let stepsInt = Int(line) ?? 0

    if stepsInt >= 0 {
        totalSteps += UInt(stepsInt)
    }
}

print("Всего шагов за 3 дня: \(totalSteps)")

Да, мы здесь «молча игнорируем» отрицательные числа (просто не прибавляем). В реальном приложении вы бы, скорее всего, печатали сообщение об ошибке — но сегодня мы тренируем типы и диапазоны, а не UX.

Разница шагов: где UInt начинает мешать

Допустим, вы хотите сравнить два дня: сегодня и вчера. Разница может быть отрицательной («сегодня прошёл меньше»). Значит, разницу лучше хранить в Int.

import Foundation

let yesterday: UInt = 8000
let today: UInt = 6500

let diff = Int(today) - Int(yesterday)
print("Разница (сегодня - вчера) = \(diff)")

Обратите внимание: мы не пытаемся вычитать UInt - UInt и получить отрицательное (это по смыслу невозможно). Мы переводим в Int, делаем честную разницу, и получаем результат, который действительно может быть отрицательным.

7. Типичные ошибки

Ошибка №1: выбирать UInt, потому что «шаги/возраст/количество — неотрицательные», и потом страдать с вычислениями.
UInt выглядит логично, пока вы не захотите посчитать разницу, штраф, изменение, отклонение от нормы или «сколько не хватает до цели». Как только в задаче появляется «может быть меньше», вам нужен знаковый тип. Часто проще хранить в Int, а неотрицательность обеспечивать проверками в if.

Ошибка №2: пытаться складывать и сравнивать разные целые типы без приведения.
Ситуация «Int плюс Int64» кажется очевидной человеку, но не компилятору: Swift требует явного решения, к какому типу вы приводите выражение. Привыкайте выбирать один «главный» тип в формуле и приводить остальные числа к нему — так код становится предсказуемым.

Ошибка №3: думать, что Int всегда 64-битный, и строить логику на этом предположении.
На большинстве ваших устройств это действительно так, но сама идея неверная: Int — платформенно-зависимый по размеру. Если вам принципиально нужен фиксированный формат (например, строго 64 бита), тогда используйте Int64 и считайте это частью контракта вашего кода.

Ошибка №4: игнорировать min/max и удивляться «случайным» падениям при больших значениях.
Переполнение редко проявляется в первых учебных задачах, но оно отлично проявляется в «настоящих» вычислениях: суммы, счётчики, большие входные данные. Хорошая привычка — помнить, что у типа есть границы (Int.max, UInt.max) и иногда ставить предохранитель перед опасными операциями.

Ошибка №5: превращать любые ошибки ввода в 0 и считать, что этого достаточно.
Конструкция Int(line) ?? 0 полезна как «первый шаг», но она может скрывать проблему: пользователь ввёл ерунду, а программа молча приняла это за ноль. В учебных примерах это нормально, но дальше старайтесь хотя бы различать «не число» и «число, но не подходит по смыслу» — это делает программы намного надёжнее.

1
Задача
Swift SELF, 6 уровень, 1 лекция
Недоступна
Паспорт типов
Паспорт типов
1
Задача
Swift SELF, 6 уровень, 1 лекция
Недоступна
Возраст в UInt
Возраст в UInt
1
Задача
Swift SELF, 6 уровень, 1 лекция
Недоступна
Защита Int64
Защита Int64
1
Задача
Swift SELF, 6 уровень, 1 лекция
Недоступна
Шаги за неделю
Шаги за неделю
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ