Большинству разработчиков использование целых чисел может показаться волшебством. Сегодня, чтобы стать продуктивным кодировщиком, требуется перспектива с высоты 100 000 футов или выше. Но задумывались ли вы о различных типах целых чисел? Почему нельзя просто написать код с максимальным диапазоном целых чисел, например 64-битный целочисленный тип? Время от времени вы также сталкиваетесь с ошибкой загадочного типа, пытаясь преобразовать числовой тип в другой. Эта статья призвана объяснить вам, что скрывается за этими ничего не подозревающими числовыми типами.

Архитектура набора команд

Полезно хотя бы понять компьютер на уровне архитектуры набора команд. Архитектура набора команд или ISA - это уровень абстракции над процессором компьютера. Think API плюс соглашение об обслуживании, позволяющее операционным системам и языковым компиляторам взаимодействовать с голым железом, оставляя разработчикам компьютеров возможность исследовать различные аппаратные реализации. ISA определяет поддерживаемые типы данных (то есть 32-битный ISA не определяет такие типы, как 64-битные целочисленные типы), какое состояние существует (например, основная память и регистры) и т. Д. Обычно вы не будете консультироваться с ISA, если не программируете на ассемблере. Поскольку на данный момент наиболее популярным и широко используемым ISA является 64-битная x86, которая касается процессоров с максимальным количеством 64 бит, которые они могут обрабатывать за такт. Думайте о тактах как о цикле, в котором на каждой итерации вычисление может обрабатываться ЦП.

Возможно, вы слышали о таких именах, как x86, PowerPC, Arm, RISC-V и новейший Apple M1. Это все ISA.

Бинарный праймер

Чтобы понять числовые типы, вы должны понимать, как они представлены - в двоичном формате. Это краткое руководство по представлению целых чисел на большинстве компьютеров, известное как комплимент двойки. Чтобы сделать это проще и лаконичнее, мы будем работать с 5-битными двоичными цифрами. С этого момента в этой статье я буду добавлять 0b перед любой строкой двоичных цифр, чтобы проводить четкое различие между двоичной строкой, такой как 0b 100000 (32), и десятичным числом 100000. (100 000).

Бит имеет два состояния: 0 или 1. Внутри компьютера они представлены отсутствием и наличием напряжения в проводе. В основном, провод без напряжения или с низким напряжением означает 0, и наоборот. Все типы данных представлены электронами.

Один бит может представлять только 2¹ чисел, 0 и 1. Два бита могут представлять 2² = 4 числа, три бита могут представлять 2³ = 8 чисел и так далее, как показано ниже:

00 = 0
01 = 1
10 = 2
11 = 3

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7

С помощью n битов можно представить 2 ^ n чисел.

Теперь мы работаем с 5-битными двоичными цифрами, мы можем представить 2⁵ = 32 разных числа. Вместо того, чтобы складывать их всех в длинную таблицу, мы обратимся к этому уравнению:

e * 2⁴ + d * 2³ + c * 2² + b * 2¹ + a * 2⁰

Где a, b, c, d и e - двоичные коэффициенты, которые могут быть либо 0, либо 1. Например, вот как получается число 12 из 5-битного двоичного числа:

= 0 * 2⁴ + 1 * 2³ + 1 * 2² + 0 * 2¹ + 0 * 2⁰
= 0 + 8 + 4 + 0 + 0
= 12

Выбирая коэффициенты, вы получаете 0b 01100.

Если бы существовал 5-разрядный целочисленный тип без знака, он представлял бы 2⁵ целых чисел в диапазоне от 0 до 31. 32-разрядный целочисленный тип без знака может представлять 2³² целых числа от 0 до 4 294 967 295 и наоборот.

Подписанные целые числа

Когда дело доходит до целых чисел со знаком, здесь нужно немного взломать. Существует пара стандартов, но общий, используемый сегодня буквально всеми компьютерами, является дополнением к двум. Вернемся к нашим 5-битным двоичным цифрам. Теперь мы знаем, что 5-битный двоичный файл может представлять 2⁵ целых чисел от 0 до 31. Как нам представить отрицательные целые числа с помощью 5 битов? Самый простой и интуитивно понятный способ - разделить их пополам и назначить одну половину для представления отрицательных целых чисел, сохраняя при этом другую половину для положительных целых чисел. Положительные целые числа начинаются от 0 (0b 00000) до 15 (0b 01111). На другом конце отрицательные целые числа начинаются с -16 (0b 10000) до -1 (0b 11111). Это дает 5-битную возможность представления целых чисел со знаком от -16 до 15, 2⁵ = 32 целых числа со знаком. Предпочтение двойки комплиментам по сравнению с другими способами просто практично. Гораздо проще разработать компьютер с дополнением Two, поскольку арифметические операции типа -1 (0b 11111) + 1 (0b 00001) всегда возвращают прямой результат, который в данном case - 0 (0b 00000).

Точно так же 32-битный целочисленный тип со знаком может представлять 2 ² целых числа со знаком в диапазоне от -2 147 483 648 до 2 147 483 647.

Максимальные положительные и отрицательные границы n-разрядного целочисленного типа со знаком можно вычислить следующим образом:

MAX_POS = 2^n / 2 - 1
MAX_NEG = -1 * 2^n / 2

На вашем любимом языке попробуйте прибавить 1 к 2 147 483 647 32-битному целому числу со знаком. Какой результат вы получите?