# Целые числа в Java: теория и практика ## 1. Что такое целые числа и зачем они нужны **Целое число** — это число без дробной части: ..., −3, −2, −1, 0, 1, 2, 3, ... В программировании целые числа используются для: - счёта объектов (количество учеников, итераций цикла); - индексов массивов и коллекций; - идентификаторов (номер заказа, ID пользователя); - работы с денежными суммами в копейках/центах (чтобы избежать ошибок округления); - битовых операций и работы с памятью. > ⚠️ **Важно:** в Java нельзя хранить в целочисленной переменной дробное значение — компилятор выдаст ошибку или потребует явного приведения. --- ## 2. Примитивные целочисленные типы В Java **4 примитивных целочисленных типа**, различающихся диапазоном и объёмом памяти: | Тип | Размер | Диапазон | Применение | |-----|--------|----------|------------| | `byte` | 8 бит | от −128 до 127 | экономия памяти в массивах, работа с байтами | | `short` | 16 бит | от −32 768 до 32 767 | редко, в основном в устаревшем коде | | `int` | 32 бита | от −2 147 483 648 до 2 147 483 647 | **основной тип по умолчанию** | | `long` | 64 бита | от −9.2·10¹⁸ до 9.2·10¹⁸ | большие числа, время в миллисекундах | **Запомните:** по умолчанию любое целое литеральное число в Java имеет тип `int`. Чтобы получить `long`, добавьте суффикс `L`: ```java int a = 2_000_000_000; // ок long b = 9_000_000_000L; // без L будет ошибка компиляции ``` --- ## 3. Объявление переменных и литералы ```java byte small = 100; short medium = 30_000; int normal = 1_000_000; long big = 123_456_789_012L; // Системы счисления: int decimal = 255; // 10-я int hex = 0xFF; // 16-я (префикс 0x) int binary = 0b1111_1111; // 2-я (префикс 0b) int octal = 0377; // 8-я (ведущий 0) // Подчёркивания для читаемости int million = 1_000_000; ``` **Константы** (`final`) — значение нельзя изменить после инициализации: ```java final int MAX_SCORE = 100; // MAX_SCORE = 200; // ошибка компиляции ``` --- ## 4. Ввод целых чисел (класс `Scanner`) Самый простой способ — `java.util.Scanner`. ```java import java.util.Scanner; public class InputDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Введите целое число: "); int n = sc.nextInt(); // читает int System.out.print("Введите длинное число: "); long L = sc.nextLong(); // читает long System.out.print("Введите байт: "); byte b = sc.nextByte(); System.out.println(String.format("Вы ввели: %d, %d, %d", n, L, b)); sc.close(); } } ``` Для чтения из файла/строки можно использовать `Scanner(new File("input.txt"))` или `BufferedReader`. --- ## 5. Вывод целых чисел ```java int x = 42; // Если нужно вывести только число — подходит обычный println: System.out.println(x); // 42 // Когда нужен текст или форматирование — String.format: System.out.println(String.format("x = %d", x)); // Форматирование в разных системах счисления: System.out.println(String.format("hex = %x, bin = %s", 255, Integer.toBinaryString(255))); // hex = ff, bin = 11111111 // Выравнивание и ширина поля: System.out.println(String.format("|%5d|", 42)); // | 42| System.out.println(String.format("|%-5d|", 42)); // |42 | System.out.println(String.format("|%05d|", 42)); // |00042| ``` Часто используемые спецификаторы `String.format`: | Спецификатор | Смысл | |--------------|-------| | `%d` | целое в 10-й системе | | `%x` | 16-я система | | `%o` | 8-я система | | `%05d` | целое с ведущими нулями, ширина 5 | | `%n` | перевод строки (переносимый) | --- ## 6. Основные операции ### 6.1 Арифметические ```java int a = 17, b = 5; System.out.println(a + b); // 22 System.out.println(a - b); // 12 System.out.println(a * b); // 85 System.out.println(a / b); // 3 — ЦЕЛОЧИСЛЕННОЕ деление System.out.println(a % b); // 2 — остаток от деления ``` > ⚠️ Деление целых чисел **отбрасывает дробную часть**, а не округляет: `7 / 2 == 3`, `-7 / 2 == -3` (округление к нулю). ### 6.2 Операции присваивания ```java int x = 10; x += 5; // x = 15 x -= 3; // x = 12 x *= 2; // x = 24 x /= 4; // x = 6 x %= 4; // x = 2 x++; // x = 3 x--; // x = 2 ``` ### 6.3 Сравнение ```java int p = 5, q = 7; boolean r1 = p == q; // false boolean r2 = p != q; // true boolean r3 = p < q; // true boolean r4 = p >= q; // false ``` ### 6.4 Побитовые операции ```java int m = 0b1100; // 12 int n = 0b1010; // 10 System.out.println(m & n); // 8 System.out.println(m | n); // 14 System.out.println(m ^ n); // 6 System.out.println(~m); // -13 System.out.println(m << 1); // 24 (сдвиг влево = ×2) System.out.println(m >> 1); // 6 (сдвиг вправо) System.out.println(m >>> 1); // 6 (беззнаковый сдвиг) ``` ### 6.5 Приведение типов **Автоматическое** (расширяющее) — от меньшего к большему: ```java byte b = 100; int i = b; // ок long l = i; // ок ``` **Явное** (сужающее) — от большего к меньшему, возможна потеря данных: ```java int big = 300; byte small = (byte) big; // 300 % 256 = 44 (переполнение) ``` **Переполнение** — опасная ситуация: `int` не может выйти за пределы диапазона и «зацикливается»: ```java int max = Integer.MAX_VALUE; System.out.println(max + 1); // -2147483648 ``` --- ## 7. Критерии применимости целых чисел Используйте целочисленный тип, если: 1. **Величина по своей природе дискретна** — количество, индекс, счётчик. 2. **Нужна точность без округлений** — деньги (лучше в копейках), ID, временные метки. 3. **Выполняются операции над целыми** — деление нацело, остаток, битовые сдвиги. 4. **Важна производительность** — целочисленная арифметика быстрее вещественной. 5. **Нужна экономия памяти** — например, `byte[]` для большого массива. **Не используйте целые числа**, если: - величина непрерывна (расстояние, температура, вес) — берите `double`/`float`; - нужна высокая точность над дробными числами — `BigDecimal`. **Выбор типа:** - по умолчанию — `int`; - если значения > 2·10⁹ или работа со временем в мс — `long`; - для больших массивов малых чисел — `byte`/`short`; - для чисел, не помещающихся ни в один примитив (> 9.2·10¹⁸) — `BigInteger`. --- ## 8. Классы стандартной библиотеки ### 8.1 Классы-обёртки: `Integer`, `Long`, `Short`, `Byte` Каждому примитиву соответствует класс-обёртка. Нужен для: - хранения в коллекциях (`ArrayList`); - использования полезных методов; - `null`-значений (например, «значение отсутствует»). ```java Integer obj = 42; // автоупаковка (autoboxing) int prim = obj; // автораспаковка (unboxing) // Полезные методы (там, где выводится только число — println): System.out.println(Integer.MAX_VALUE); // 2147483647 System.out.println(Integer.MIN_VALUE); // -2147483648 System.out.println(Integer.parseInt("123")); // 123 System.out.println(Integer.compare(3, 5)); // -1 System.out.println(Integer.max(3, 5)); // 5 System.out.println(Integer.sum(3, 5)); // 8 System.out.println(Integer.bitCount(7)); // 3 System.out.println(Integer.numberOfLeadingZeros(1)); // 31 // Там, где результат — строка — String.format: System.out.println(String.format("%s", Integer.toBinaryString(10))); // 1010 System.out.println(String.format("%s", Integer.toHexString(255))); // ff ``` > ⚠️ Сравнивайте объекты-обёртки через `.equals()`, а не `==`: > ```java > Integer a = 1000, b = 1000; > System.out.println(a == b); // false (разные объекты) > System.out.println(a.equals(b)); // true > ``` > Кэш `Integer` работает только для значений от −128 до 127, поэтому `Integer a = 100; Integer b = 100; a == b` даст `true`, но для 1000 — уже `false`. ### 8.2 `BigInteger` — для чисел произвольной длины Когда `long` недостаточно (факториалы, криптография, длинная арифметика): ```java import java.math.BigInteger; BigInteger a = new BigInteger("123456789012345678901234567890"); BigInteger b = BigInteger.valueOf(987654321L); System.out.println(a.add(b)); // сложение System.out.println(a.subtract(b)); // вычитание System.out.println(a.multiply(b)); // умножение System.out.println(a.divide(b)); // деление System.out.println(a.mod(b)); // остаток System.out.println(a.pow(2)); // возведение в степень System.out.println(a.gcd(b)); // НОД // Факториал 100: BigInteger fact = BigInteger.ONE; for (int i = 2; i <= 100; i++) fact = fact.multiply(BigInteger.valueOf(i)); System.out.println(fact); ``` `BigInteger` **иммутабелен** — операции возвращают новый объект, а не меняют исходный. ### 8.3 `Math` — математические функции Работает с `double`, но есть методы и для целых: ```java System.out.println(Math.abs(-7)); // 7 System.out.println(Math.max(3, 8)); // 8 System.out.println(Math.min(3, 8)); // 3 // Math.pow / Math.sqrt возвращают double — для форматирования используем String.format: System.out.println(String.format("%.1f", Math.pow(2, 10))); // 1024.0 System.out.println(String.format("%.1f", Math.sqrt(144))); // 12.0 ``` ### 8.4 `Random` — генерация случайных чисел ```java import java.util.Random; Random rnd = new Random(); int r1 = rnd.nextInt(); // любое int int r2 = rnd.nextInt(100); // [0, 100) int r3 = rnd.nextInt(50) + 1; // [1, 50] System.out.println(r2); System.out.println(r3); // Начиная с Java 17 — RandomGenerator: // int r = java.util.random.RandomGenerator.getDefault().nextInt(1, 101); ``` --- ## 9. Мини-пример: сумма цифр числа ```java import java.util.Scanner; public class SumDigits { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Введите целое число: "); long n = Math.abs(sc.nextLong()); int sum = 0; while (n > 0) { sum += (int)(n % 10); // последняя цифра n /= 10; // отбрасываем её } System.out.println(sum); } } ``` Здесь задействованы: `long`, `%` и `/`, приведение типов, ввод/вывод, `Math.abs`. --- ## 10. Типичные ошибки | Ошибка | Как избежать | |--------|--------------| | Деление нацело вместо дробного | Привести один операнд: `(double) a / b` | | Переполнение `int` | Использовать `long` или `Math.addExact` (бросает исключение) | | Сравнение обёрток через `==` | Использовать `.equals()` | | Забыть `L` у большого литерала | `long x = 3000000000L;` | | `NullPointerException` при распаковке | Проверять на `null` перед присваиванием в примитив | | Потеря точности при `(int) longValue` | Проверять диапазон или использовать `Math.toIntExact` | ```java // Безопасные операции (Java 8+): int sum = Math.addExact(1_000_000_000, 1_000_000_000); // ArithmeticException int prod = Math.multiplyExact(100_000, 100_000); // исключение ``` --- ## 11. Итоги - В Java 4 примитивных целочисленных типа; основной — `int`, для больших значений — `long`. - По умолчанию целые литералы — `int`, для `long` нужен суффикс `L`. - Деление целых **отбрасывает** дробную часть, остаток даёт `%`. - Для чисел > 9.2·10¹⁸ используйте `BigInteger`. - Для коллекций и `null` — классы-обёртки (`Integer`, `Long`, ...). - Всегда проверяйте возможность **переполнения** и корректность приведения типов.