Откуда берутся минимальное и максимальное значения int?
Минимальное и максимальное значения типа int в Java определяются исходя из размера и способа представления данных в памяти. Тип int в Java является примитивным типом, который занимает 4 байта (32 бита) и представляет собой знаковое целое число, используя дополнительный код (two's complement) для хранения отрицательных значений.
Бинарное представление int и диапазон значений
Тип int в Java имеет строго определённый размер:
-
Размер: 32 бита (4 байта)
-
Представление: знаковое, с использованием **дополнительного кода (two’s complement)
**
Дополнительный код — это система, в которой:
-
самый старший бит (левый, старший) является знаковым битом:
-
0 — положительное число,
-
1 — отрицательное.
-
-
диапазон значений асимметричен: на одно отрицательное число больше, чем положительных.
Расчёт диапазона значений
Общий диапазон для 32-битного знакового целого числа:
-
Минимальное значение: -2^31 = -2,147,483,648
-
Максимальное значение: 2^31 - 1 = 2,147,483,647
Таким образом:
public static final int MIN_VALUE = -2147483648;
public static final int MAX_VALUE = 2147483647;
Они доступны в классе-обёртке java.lang.Integer как **константы**:
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Integer.MAX_VALUE); // 2147483647
Почему максимальное значение меньше по модулю, чем минимальное?
Это связано с тем, что:
-
Всего возможно представить 2^32 = 4,294,967,296 различных комбинаций битов.
-
Из-за наличия знака, половина этих комбинаций (2^31) отводится под отрицательные значения, одна — под ноль, и оставшиеся — под положительные значения.
Поскольку 0 считается неотрицательным, то:
-
Отрицательных чисел: 2^31 (включая -2^31)
-
Положительных: 2^31 - 1 (от 1 до 2^31 - 1)
-
0 занимает отдельную ячейку в положительной части
Таким образом, отрицательных значений на одно больше, чем положительных.
Бинарный пример
- int в Java — 32-битное значение:
Примеры:
-
0 в двоичном виде: 00000000 00000000 00000000 00000000
-
1: 00000000 00000000 00000000 00000001
-
-1: 11111111 11111111 11111111 11111111
-
Integer.MAX_VALUE: 01111111 11111111 11111111 11111111 = 2,147,483,647
-
Integer.MIN_VALUE: 10000000 00000000 00000000 00000000 = -2,147,483,648
При попытке выйти за пределы этого диапазона произойдёт переполнение (overflow):
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // Вывод: -2147483648 (переполнение)
int min = Integer.MIN_VALUE;
System.out.println(min - 1); // Вывод: 2147483647 (переполнение)
Это объясняется тем, что Java не генерирует исключений при переполнении целочисленных типов. Числа "переворачиваются" по кругу в пределах 32-битной области.
Как JVM обрабатывает int на уровне байтов
На уровне байт, int занимает 4 байта и хранится в двухкомплементарной форме, которая является стандартом для большинства современных процессоров и языков программирования.
Пример:
int a = -1;
Значение a в памяти будет: 0xFFFFFFFF, то есть каждый бит равен 1.
Для Integer.MIN_VALUE (-2147483648) это будет:
10000000 00000000 00000000 00000000
Для Integer.MAX_VALUE (2147483647) это будет:
01111111 11111111 11111111 11111111
Почему используется дополнительный код
Дополнительный код (two's complement) выбран в качестве стандарта представления целых чисел в Java (и в большинстве языков) по следующим причинам:
-
Одна уникальная нулевая комбинация: 0x00000000, а не две (как в знако-величинной форме).
-
Арифметические операции одинаковы как для положительных, так и для отрицательных чисел — не требуется специальная логика.
-
Упрощённая реализация на уровне процессора.
-
Возможность сравнения знаков по старшему биту.
Связь с другими типами
Аналогичным образом рассчитываются минимальные и максимальные значения других примитивных типов в Java:
Тип | Размер | Мин. значение | Макс. значение |
---|---|---|---|
byte | 8 бит | -2^7 = -128 | 2^7 - 1 = 127 |
--- | --- | --- | --- |
short | 16 бит | -2^15 = -32,768 | 2^15 - 1 = 32,767 |
--- | --- | --- | --- |
int | 32 бит | -2^31 = -2,147,483,648 | 2^31 - 1 = 2,147,483,647 |
--- | --- | --- | --- |
long | 64 бит | -2^63 | 2^63 - 1 |
--- | --- | --- | --- |
Все знаковые типы используют дополнительный код.
Где хранятся MIN_VALUE и MAX_VALUE
Они определены в классе-обёртке java.lang.Integer как публичные статические финальные константы:
public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = 0x80000000; // -2147483648
public static final int MAX_VALUE = 0x7fffffff; // 2147483647
...
}
Значения записаны в шестнадцатеричном виде:
- 0x80000000 = 10000000 00000000 00000000 00000000 (32 бита)
- 0x7FFFFFFF = 01111111 11111111 11111111 11111111 (32 бита)
Эти значения не меняются и доступны в любом месте программы как:
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;
Они также применяются при проверках на переполнение, при сериализации, генерации диапазонов и других числовых операциях.